|
| 1 | +From 2852bab291d87a6d9ff1af089c879b9f155c7be1 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Nick Desaulniers < [email protected]> |
| 3 | +Date: Wed, 13 Mar 2019 10:34:50 -0700 |
| 4 | +Subject: [PATCH v4] lib/string.c: implement a basic bcmp |
| 5 | + |
| 6 | +A recent optimization in Clang (r355672) lowers comparisons of the |
| 7 | +return value of memcmp against zero to comparisons of the return value |
| 8 | +of bcmp against zero. This helps some platforms that implement bcmp |
| 9 | +more efficiently than memcmp. glibc simply aliases bcmp to memcmp, but |
| 10 | +an optimized implementation is in the works. |
| 11 | + |
| 12 | +This results in linkage failures for all targets with Clang due to the |
| 13 | +undefined symbol. For now, just implement bcmp as a tailcail to memcmp |
| 14 | +to unbreak the build. This routine can be further optimized in the |
| 15 | +future. |
| 16 | + |
| 17 | +Other ideas discussed: |
| 18 | +* A weak alias was discussed, but breaks for architectures that define |
| 19 | +their own implementations of memcmp since aliases to declarations are |
| 20 | +not permitted (only definitions). Arch-specific memcmp implementations |
| 21 | +typically declare memcmp in C headers, but implement them in assembly. |
| 22 | +* -ffreestanding also is used sporadically throughout the kernel. |
| 23 | +* -fno-builtin-bcmp doesn't work when doing LTO. |
| 24 | + |
| 25 | +Link: https://bugs.llvm.org/show_bug.cgi?id=41035 |
| 26 | +Link: https://code.woboq.org/userspace/glibc/string/memcmp.c.html#bcmp |
| 27 | +Link: https://github.com/llvm/llvm-project/commit/8e16d73346f8091461319a7dfc4ddd18eedcff13 |
| 28 | +Link: https://github.com/ClangBuiltLinux/linux/issues/416 |
| 29 | + |
| 30 | +Reported-by: Nathan Chancellor < [email protected]> |
| 31 | +Reported-by: Adhemerval Zanella < [email protected]> |
| 32 | +Suggested-by: Arnd Bergmann < [email protected]> |
| 33 | +Suggested-by: James Y Knight < [email protected]> |
| 34 | +Suggested-by: Masahiro Yamada < [email protected]> |
| 35 | +Suggested-by: Nathan Chancellor < [email protected]> |
| 36 | +Suggested-by: Rasmus Villemoes < [email protected]> |
| 37 | +Signed-off-by: Nick Desaulniers < [email protected]> |
| 38 | +Acked-by: Steven Rostedt (VMware) < [email protected]> |
| 39 | +--- |
| 40 | +Changes V3 -> V4: |
| 41 | +* Include the entirety of Rasmus' sugguestion, as per Steven. |
| 42 | +* Change formal parameter identifiers to match the comment. |
| 43 | +Changes V2 -> V3: |
| 44 | +* Adjust comment as per Steven to Rasmus' sugguestion. |
| 45 | +* Pick up Steven's Ack. |
| 46 | +Changes V1 -> V2: |
| 47 | +* Add declaration to include/linux/string.h. |
| 48 | +* Reword comment above bcmp. |
| 49 | + |
| 50 | + include/linux/string.h | 3 +++ |
| 51 | + lib/string.c | 20 ++++++++++++++++++++ |
| 52 | + 2 files changed, 23 insertions(+) |
| 53 | + |
| 54 | +diff --git a/include/linux/string.h b/include/linux/string.h |
| 55 | +index 7927b875f80c..6ab0a6fa512e 100644 |
| 56 | +--- a/include/linux/string.h |
| 57 | ++++ b/include/linux/string.h |
| 58 | +@@ -150,6 +150,9 @@ extern void * memscan(void *,int,__kernel_size_t); |
| 59 | + #ifndef __HAVE_ARCH_MEMCMP |
| 60 | + extern int memcmp(const void *,const void *,__kernel_size_t); |
| 61 | + #endif |
| 62 | ++#ifndef __HAVE_ARCH_BCMP |
| 63 | ++extern int bcmp(const void *,const void *,__kernel_size_t); |
| 64 | ++#endif |
| 65 | + #ifndef __HAVE_ARCH_MEMCHR |
| 66 | + extern void * memchr(const void *,int,__kernel_size_t); |
| 67 | + #endif |
| 68 | +diff --git a/lib/string.c b/lib/string.c |
| 69 | +index 38e4ca08e757..3ab861c1a857 100644 |
| 70 | +--- a/lib/string.c |
| 71 | ++++ b/lib/string.c |
| 72 | +@@ -866,6 +866,26 @@ __visible int memcmp(const void *cs, const void *ct, size_t count) |
| 73 | + EXPORT_SYMBOL(memcmp); |
| 74 | + #endif |
| 75 | + |
| 76 | ++#ifndef __HAVE_ARCH_BCMP |
| 77 | ++/** |
| 78 | ++ * bcmp - returns 0 if and only if the buffers have identical contents. |
| 79 | ++ * @a: pointer to first buffer. |
| 80 | ++ * @b: pointer to second buffer. |
| 81 | ++ * @len: size of buffers. |
| 82 | ++ * |
| 83 | ++ * The sign or magnitude of a non-zero return value has no particular |
| 84 | ++ * meaning, and architectures may implement their own more efficient bcmp(). So |
| 85 | ++ * while this particular implementation is a simple (tail) call to memcmp, do |
| 86 | ++ * not rely on anything but whether the return value is zero or non-zero. |
| 87 | ++ */ |
| 88 | ++#undef bcmp |
| 89 | ++int bcmp(const void *a, const void *b, size_t len) |
| 90 | ++{ |
| 91 | ++ return memcmp(a, b, len); |
| 92 | ++} |
| 93 | ++EXPORT_SYMBOL(bcmp); |
| 94 | ++#endif |
| 95 | ++ |
| 96 | + #ifndef __HAVE_ARCH_MEMSCAN |
| 97 | + /** |
| 98 | + * memscan - Find a character in an area of memory. |
| 99 | +-- |
| 100 | +2.21.0.360.g471c308f928-goog |
| 101 | + |
0 commit comments