diff options
author | Akinobu Mita <akinobu.mita@gmail.com> | 2012-07-30 17:40:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-07-30 20:25:16 -0400 |
commit | 639b9e34f15e4b2c30068a4e4485586af0cdf709 (patch) | |
tree | a84e3277a55757dac4630e3d20bc353b195c3c10 /lib | |
parent | f7f95056779eb69c5fc3ac30e5cb6fd28bdbba43 (diff) |
string: introduce memweight()
memweight() is the function that counts the total number of bits set in
memory area. Unlike bitmap_weight(), memweight() takes pointer and size
in bytes to specify a memory area which does not need to be aligned to
long-word boundary.
[akpm@linux-foundation.org: rename `w' to `ret']
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Cc: Anders Larsen <al@alarsen.net>
Cc: Alasdair Kergon <agk@redhat.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Mark Fasheh <mfasheh@suse.com>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Andreas Dilger <adilger.kernel@dilger.ca>
Cc: "Theodore Ts'o" <tytso@mit.edu>
Cc: Matthew Wilcox <matthew@wil.cx>
Cc: Mauro Carvalho Chehab <mchehab@infradead.org>
Cc: Tony Luck <tony.luck@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/Makefile | 2 | ||||
-rw-r--r-- | lib/memweight.c | 38 |
2 files changed, 39 insertions, 1 deletions
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); | ||