aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--lib/Makefile1
-rw-r--r--lib/bitmap.c19
-rw-r--r--lib/find_next_bit.c177
-rw-r--r--lib/hweight.c53
5 files changed, 207 insertions, 45 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 7e70ab13e191..6e8a60f67c7a 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -172,7 +172,7 @@ config DEBUG_IOREMAP
172 172
173config DEBUG_FS 173config DEBUG_FS
174 bool "Debug Filesystem" 174 bool "Debug Filesystem"
175 depends on DEBUG_KERNEL && SYSFS 175 depends on SYSFS
176 help 176 help
177 debugfs is a virtual file system that kernel developers use to put 177 debugfs is a virtual file system that kernel developers use to put
178 debugging files into. Enable this option to be able to read and 178 debugging files into. Enable this option to be able to read and
diff --git a/lib/Makefile b/lib/Makefile
index f827e3c24ec0..b830c9a15541 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,6 +23,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
23lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o 23lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
24lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o 24lib-$(CONFIG_SEMAPHORE_SLEEPERS) += semaphore-sleepers.o
25lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o 25lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
26lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
26obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o 27obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
27obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o 28obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
28 29
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 8acab0e176ef..ed2ae3b0cd06 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -253,33 +253,18 @@ int __bitmap_subset(const unsigned long *bitmap1,
253} 253}
254EXPORT_SYMBOL(__bitmap_subset); 254EXPORT_SYMBOL(__bitmap_subset);
255 255
256#if BITS_PER_LONG == 32
257int __bitmap_weight(const unsigned long *bitmap, int bits) 256int __bitmap_weight(const unsigned long *bitmap, int bits)
258{ 257{
259 int k, w = 0, lim = bits/BITS_PER_LONG; 258 int k, w = 0, lim = bits/BITS_PER_LONG;
260 259
261 for (k = 0; k < lim; k++) 260 for (k = 0; k < lim; k++)
262 w += hweight32(bitmap[k]); 261 w += hweight_long(bitmap[k]);
263 262
264 if (bits % BITS_PER_LONG) 263 if (bits % BITS_PER_LONG)
265 w += hweight32(bitmap[k] & BITMAP_LAST_WORD_MASK(bits)); 264 w += hweight_long(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
266 265
267 return w; 266 return w;
268} 267}
269#else
270int __bitmap_weight(const unsigned long *bitmap, int bits)
271{
272 int k, w = 0, lim = bits/BITS_PER_LONG;
273
274 for (k = 0; k < lim; k++)
275 w += hweight64(bitmap[k]);
276
277 if (bits % BITS_PER_LONG)
278 w += hweight64(bitmap[k] & BITMAP_LAST_WORD_MASK(bits));
279
280 return w;
281}
282#endif
283EXPORT_SYMBOL(__bitmap_weight); 268EXPORT_SYMBOL(__bitmap_weight);
284 269
285/* 270/*
diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
index c05b4b19cf6c..bda0d71a2514 100644
--- a/lib/find_next_bit.c
+++ b/lib/find_next_bit.c
@@ -11,48 +11,171 @@
11 11
12#include <linux/bitops.h> 12#include <linux/bitops.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <asm/types.h>
15#include <asm/byteorder.h>
14 16
15int find_next_bit(const unsigned long *addr, int size, int offset) 17#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
18
19/**
20 * find_next_bit - find the next set bit in a memory region
21 * @addr: The address to base the search on
22 * @offset: The bitnumber to start searching at
23 * @size: The maximum size to search
24 */
25unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
26 unsigned long offset)
16{ 27{
17 const unsigned long *base; 28 const unsigned long *p = addr + BITOP_WORD(offset);
18 const int NBITS = sizeof(*addr) * 8; 29 unsigned long result = offset & ~(BITS_PER_LONG-1);
19 unsigned long tmp; 30 unsigned long tmp;
20 31
21 base = addr; 32 if (offset >= size)
33 return size;
34 size -= result;
35 offset %= BITS_PER_LONG;
22 if (offset) { 36 if (offset) {
23 int suboffset; 37 tmp = *(p++);
38 tmp &= (~0UL << offset);
39 if (size < BITS_PER_LONG)
40 goto found_first;
41 if (tmp)
42 goto found_middle;
43 size -= BITS_PER_LONG;
44 result += BITS_PER_LONG;
45 }
46 while (size & ~(BITS_PER_LONG-1)) {
47 if ((tmp = *(p++)))
48 goto found_middle;
49 result += BITS_PER_LONG;
50 size -= BITS_PER_LONG;
51 }
52 if (!size)
53 return result;
54 tmp = *p;
24 55
25 addr += offset / NBITS; 56found_first:
57 tmp &= (~0UL >> (BITS_PER_LONG - size));
58 if (tmp == 0UL) /* Are any bits set? */
59 return result + size; /* Nope. */
60found_middle:
61 return result + __ffs(tmp);
62}
26 63
27 suboffset = offset % NBITS; 64EXPORT_SYMBOL(find_next_bit);
28 if (suboffset) {
29 tmp = *addr;
30 tmp >>= suboffset;
31 if (tmp)
32 goto finish;
33 }
34 65
35 addr++; 66/*
67 * This implementation of find_{first,next}_zero_bit was stolen from
68 * Linus' asm-alpha/bitops.h.
69 */
70unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
71 unsigned long offset)
72{
73 const unsigned long *p = addr + BITOP_WORD(offset);
74 unsigned long result = offset & ~(BITS_PER_LONG-1);
75 unsigned long tmp;
76
77 if (offset >= size)
78 return size;
79 size -= result;
80 offset %= BITS_PER_LONG;
81 if (offset) {
82 tmp = *(p++);
83 tmp |= ~0UL >> (BITS_PER_LONG - offset);
84 if (size < BITS_PER_LONG)
85 goto found_first;
86 if (~tmp)
87 goto found_middle;
88 size -= BITS_PER_LONG;
89 result += BITS_PER_LONG;
90 }
91 while (size & ~(BITS_PER_LONG-1)) {
92 if (~(tmp = *(p++)))
93 goto found_middle;
94 result += BITS_PER_LONG;
95 size -= BITS_PER_LONG;
36 } 96 }
97 if (!size)
98 return result;
99 tmp = *p;
100
101found_first:
102 tmp |= ~0UL << size;
103 if (tmp == ~0UL) /* Are any bits zero? */
104 return result + size; /* Nope. */
105found_middle:
106 return result + ffz(tmp);
107}
108
109EXPORT_SYMBOL(find_next_zero_bit);
37 110
38 while ((tmp = *addr) == 0) 111#ifdef __BIG_ENDIAN
39 addr++;
40 112
41 offset = (addr - base) * NBITS; 113/* include/linux/byteorder does not support "unsigned long" type */
114static inline unsigned long ext2_swabp(const unsigned long * x)
115{
116#if BITS_PER_LONG == 64
117 return (unsigned long) __swab64p((u64 *) x);
118#elif BITS_PER_LONG == 32
119 return (unsigned long) __swab32p((u32 *) x);
120#else
121#error BITS_PER_LONG not defined
122#endif
123}
124
125/* include/linux/byteorder doesn't support "unsigned long" type */
126static inline unsigned long ext2_swab(const unsigned long y)
127{
128#if BITS_PER_LONG == 64
129 return (unsigned long) __swab64((u64) y);
130#elif BITS_PER_LONG == 32
131 return (unsigned long) __swab32((u32) y);
132#else
133#error BITS_PER_LONG not defined
134#endif
135}
42 136
43 finish: 137unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned
44 /* count the remaining bits without using __ffs() since that takes a 32-bit arg */ 138 long size, unsigned long offset)
45 while (!(tmp & 0xff)) { 139{
46 offset += 8; 140 const unsigned long *p = addr + BITOP_WORD(offset);
47 tmp >>= 8; 141 unsigned long result = offset & ~(BITS_PER_LONG - 1);
142 unsigned long tmp;
143
144 if (offset >= size)
145 return size;
146 size -= result;
147 offset &= (BITS_PER_LONG - 1UL);
148 if (offset) {
149 tmp = ext2_swabp(p++);
150 tmp |= (~0UL >> (BITS_PER_LONG - offset));
151 if (size < BITS_PER_LONG)
152 goto found_first;
153 if (~tmp)
154 goto found_middle;
155 size -= BITS_PER_LONG;
156 result += BITS_PER_LONG;
48 } 157 }
49 158
50 while (!(tmp & 1)) { 159 while (size & ~(BITS_PER_LONG - 1)) {
51 offset++; 160 if (~(tmp = *(p++)))
52 tmp >>= 1; 161 goto found_middle_swap;
162 result += BITS_PER_LONG;
163 size -= BITS_PER_LONG;
53 } 164 }
165 if (!size)
166 return result;
167 tmp = ext2_swabp(p);
168found_first:
169 tmp |= ~0UL << size;
170 if (tmp == ~0UL) /* Are any bits zero? */
171 return result + size; /* Nope. Skip ffz */
172found_middle:
173 return result + ffz(tmp);
54 174
55 return offset; 175found_middle_swap:
176 return result + ffz(ext2_swab(tmp));
56} 177}
57 178
58EXPORT_SYMBOL(find_next_bit); 179EXPORT_SYMBOL(generic_find_next_zero_le_bit);
180
181#endif /* __BIG_ENDIAN */
diff --git a/lib/hweight.c b/lib/hweight.c
new file mode 100644
index 000000000000..438257671708
--- /dev/null
+++ b/lib/hweight.c
@@ -0,0 +1,53 @@
1#include <linux/module.h>
2#include <asm/types.h>
3
4/**
5 * hweightN - returns the hamming weight of a N-bit word
6 * @x: the word to weigh
7 *
8 * The Hamming Weight of a number is the total number of bits set in it.
9 */
10
11unsigned int hweight32(unsigned int w)
12{
13 unsigned int res = w - ((w >> 1) & 0x55555555);
14 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
15 res = (res + (res >> 4)) & 0x0F0F0F0F;
16 res = res + (res >> 8);
17 return (res + (res >> 16)) & 0x000000FF;
18}
19EXPORT_SYMBOL(hweight32);
20
21unsigned int hweight16(unsigned int w)
22{
23 unsigned int res = w - ((w >> 1) & 0x5555);
24 res = (res & 0x3333) + ((res >> 2) & 0x3333);
25 res = (res + (res >> 4)) & 0x0F0F;
26 return (res + (res >> 8)) & 0x00FF;
27}
28EXPORT_SYMBOL(hweight16);
29
30unsigned int hweight8(unsigned int w)
31{
32 unsigned int res = w - ((w >> 1) & 0x55);
33 res = (res & 0x33) + ((res >> 2) & 0x33);
34 return (res + (res >> 4)) & 0x0F;
35}
36EXPORT_SYMBOL(hweight8);
37
38unsigned long hweight64(__u64 w)
39{
40#if BITS_PER_LONG == 32
41 return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
42#elif BITS_PER_LONG == 64
43 __u64 res = w - ((w >> 1) & 0x5555555555555555ul);
44 res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
45 res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
46 res = res + (res >> 8);
47 res = res + (res >> 16);
48 return (res + (res >> 32)) & 0x00000000000000FFul;
49#else
50#error BITS_PER_LONG not defined
51#endif
52}
53EXPORT_SYMBOL(hweight64);