diff options
-rw-r--r-- | include/linux/string.h | 3 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/memweight.c | 38 |
3 files changed, 42 insertions, 1 deletions
diff --git a/include/linux/string.h b/include/linux/string.h index e033564f10ba..ffe0442e18d2 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
@@ -145,4 +145,7 @@ static inline bool strstarts(const char *str, const char *prefix) | |||
145 | return strncmp(str, prefix, strlen(prefix)) == 0; | 145 | return strncmp(str, prefix, strlen(prefix)) == 0; |
146 | } | 146 | } |
147 | #endif | 147 | #endif |
148 | |||
149 | extern size_t memweight(const void *ptr, size_t bytes); | ||
150 | |||
148 | #endif /* _LINUX_STRING_H_ */ | 151 | #endif /* _LINUX_STRING_H_ */ |
diff --git a/lib/Makefile b/lib/Makefile index 8c31a0cb75e9..df663cc05c73 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -22,7 +22,7 @@ lib-y += kobject.o klist.o | |||
22 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ | 22 | obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \ |
23 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ | 23 | bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \ |
24 | string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \ | 24 | string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o \ |
25 | bsearch.o find_last_bit.o find_next_bit.o llist.o | 25 | bsearch.o find_last_bit.o find_next_bit.o llist.o memweight.o |
26 | obj-y += kstrtox.o | 26 | obj-y += kstrtox.o |
27 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o | 27 | obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o |
28 | 28 | ||
diff --git a/lib/memweight.c b/lib/memweight.c new file mode 100644 index 000000000000..e35fc8771893 --- /dev/null +++ b/lib/memweight.c | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <linux/export.h> | ||
2 | #include <linux/bug.h> | ||
3 | #include <linux/bitmap.h> | ||
4 | |||
5 | /** | ||
6 | * memweight - count the total number of bits set in memory area | ||
7 | * @ptr: pointer to the start of the area | ||
8 | * @bytes: the size of the area | ||
9 | */ | ||
10 | size_t memweight(const void *ptr, size_t bytes) | ||
11 | { | ||
12 | size_t ret = 0; | ||
13 | size_t longs; | ||
14 | const unsigned char *bitmap = ptr; | ||
15 | |||
16 | for (; bytes > 0 && ((unsigned long)bitmap) % sizeof(long); | ||
17 | bytes--, bitmap++) | ||
18 | ret += hweight8(*bitmap); | ||
19 | |||
20 | longs = bytes / sizeof(long); | ||
21 | if (longs) { | ||
22 | BUG_ON(longs >= INT_MAX / BITS_PER_LONG); | ||
23 | ret += bitmap_weight((unsigned long *)bitmap, | ||
24 | longs * BITS_PER_LONG); | ||
25 | bytes -= longs * sizeof(long); | ||
26 | bitmap += longs * sizeof(long); | ||
27 | } | ||
28 | /* | ||
29 | * The reason that this last loop is distinct from the preceding | ||
30 | * bitmap_weight() call is to compute 1-bits in the last region smaller | ||
31 | * than sizeof(long) properly on big-endian systems. | ||
32 | */ | ||
33 | for (; bytes > 0; bytes--, bitmap++) | ||
34 | ret += hweight8(*bitmap); | ||
35 | |||
36 | return ret; | ||
37 | } | ||
38 | EXPORT_SYMBOL(memweight); | ||