aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAkinobu Mita <akinobu.mita@gmail.com>2011-10-31 20:08:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-31 20:30:47 -0400
commit798248206b59acc6e1238c778281419c041891a7 (patch)
treeff8564431367b442b18bca4a0a9732e5799e2391 /lib
parent77311139f364d7f71fc9ba88f59fd90e60205007 (diff)
lib/string.c: introduce memchr_inv()
memchr_inv() is mainly used to check whether the whole buffer is filled with just a specified byte. The function name and prototype are stolen from logfs and the implementation is from SLUB. Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com> Acked-by: Christoph Lameter <cl@linux-foundation.org> Acked-by: Pekka Enberg <penberg@kernel.org> Cc: Matt Mackall <mpm@selenic.com> Acked-by: Joern Engel <joern@logfs.org> Cc: Marcin Slusarz <marcin.slusarz@gmail.com> Cc: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/string.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/string.c b/lib/string.c
index 01fad9b203e1..11df54325fb8 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -756,3 +756,57 @@ void *memchr(const void *s, int c, size_t n)
756} 756}
757EXPORT_SYMBOL(memchr); 757EXPORT_SYMBOL(memchr);
758#endif 758#endif
759
760static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
761{
762 while (bytes) {
763 if (*start != value)
764 return (void *)start;
765 start++;
766 bytes--;
767 }
768 return NULL;
769}
770
771/**
772 * memchr_inv - Find an unmatching character in an area of memory.
773 * @start: The memory area
774 * @c: Find a character other than c
775 * @bytes: The size of the area.
776 *
777 * returns the address of the first character other than @c, or %NULL
778 * if the whole buffer contains just @c.
779 */
780void *memchr_inv(const void *start, int c, size_t bytes)
781{
782 u8 value = c;
783 u64 value64;
784 unsigned int words, prefix;
785
786 if (bytes <= 16)
787 return check_bytes8(start, value, bytes);
788
789 value64 = value | value << 8 | value << 16 | value << 24;
790 value64 = (value64 & 0xffffffff) | value64 << 32;
791 prefix = 8 - ((unsigned long)start) % 8;
792
793 if (prefix) {
794 u8 *r = check_bytes8(start, value, prefix);
795 if (r)
796 return r;
797 start += prefix;
798 bytes -= prefix;
799 }
800
801 words = bytes / 8;
802
803 while (words) {
804 if (*(u64 *)start != value64)
805 return check_bytes8(start, value, 8);
806 start += 8;
807 words--;
808 }
809
810 return check_bytes8(start, value, bytes % 8);
811}
812EXPORT_SYMBOL(memchr_inv);