diff options
-rw-r--r-- | arch/arm/include/asm/bitops.h | 1 | ||||
-rw-r--r-- | arch/m68k/include/asm/bitops.h | 3 | ||||
-rw-r--r-- | arch/unicore32/include/asm/bitops.h | 2 | ||||
-rw-r--r-- | include/asm-generic/bitops/find.h | 20 | ||||
-rw-r--r-- | include/linux/bitmap.h | 6 | ||||
-rw-r--r-- | lib/cpumask.c | 9 | ||||
-rw-r--r-- | lib/find_bit.c | 59 | ||||
-rw-r--r-- | lib/find_bit_benchmark.c | 25 | ||||
-rw-r--r-- | tools/include/asm-generic/bitops/find.h | 16 | ||||
-rw-r--r-- | tools/lib/find_bit.c | 39 |
10 files changed, 147 insertions, 33 deletions
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h index ce5ee762ed66..4cab9bb823fb 100644 --- a/arch/arm/include/asm/bitops.h +++ b/arch/arm/include/asm/bitops.h | |||
@@ -338,6 +338,7 @@ static inline int find_next_bit_le(const void *p, int size, int offset) | |||
338 | 338 | ||
339 | #endif | 339 | #endif |
340 | 340 | ||
341 | #include <asm-generic/bitops/find.h> | ||
341 | #include <asm-generic/bitops/le.h> | 342 | #include <asm-generic/bitops/le.h> |
342 | 343 | ||
343 | /* | 344 | /* |
diff --git a/arch/m68k/include/asm/bitops.h b/arch/m68k/include/asm/bitops.h index dda58cfe8c22..93b47b1f6fb4 100644 --- a/arch/m68k/include/asm/bitops.h +++ b/arch/m68k/include/asm/bitops.h | |||
@@ -311,7 +311,6 @@ static inline int bfchg_mem_test_and_change_bit(int nr, | |||
311 | * functions. | 311 | * functions. |
312 | */ | 312 | */ |
313 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) | 313 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) |
314 | #include <asm-generic/bitops/find.h> | ||
315 | #include <asm-generic/bitops/ffz.h> | 314 | #include <asm-generic/bitops/ffz.h> |
316 | #else | 315 | #else |
317 | 316 | ||
@@ -441,6 +440,8 @@ static inline unsigned long ffz(unsigned long word) | |||
441 | 440 | ||
442 | #endif | 441 | #endif |
443 | 442 | ||
443 | #include <asm-generic/bitops/find.h> | ||
444 | |||
444 | #ifdef __KERNEL__ | 445 | #ifdef __KERNEL__ |
445 | 446 | ||
446 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) | 447 | #if defined(CONFIG_CPU_HAS_NO_BITFIELDS) |
diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h index 401f597bc38c..c0cbdbe17168 100644 --- a/arch/unicore32/include/asm/bitops.h +++ b/arch/unicore32/include/asm/bitops.h | |||
@@ -44,4 +44,6 @@ static inline int fls(int x) | |||
44 | #define find_first_bit find_first_bit | 44 | #define find_first_bit find_first_bit |
45 | #define find_first_zero_bit find_first_zero_bit | 45 | #define find_first_zero_bit find_first_zero_bit |
46 | 46 | ||
47 | #include <asm-generic/bitops/find.h> | ||
48 | |||
47 | #endif /* __UNICORE_BITOPS_H__ */ | 49 | #endif /* __UNICORE_BITOPS_H__ */ |
diff --git a/include/asm-generic/bitops/find.h b/include/asm-generic/bitops/find.h index 1ba611e16fa0..8a1ee10014de 100644 --- a/include/asm-generic/bitops/find.h +++ b/include/asm-generic/bitops/find.h | |||
@@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long | |||
16 | size, unsigned long offset); | 16 | size, unsigned long offset); |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #ifndef find_next_and_bit | ||
20 | /** | ||
21 | * find_next_and_bit - find the next set bit in both memory regions | ||
22 | * @addr1: The first address to base the search on | ||
23 | * @addr2: The second address to base the search on | ||
24 | * @offset: The bitnumber to start searching at | ||
25 | * @size: The bitmap size in bits | ||
26 | * | ||
27 | * Returns the bit number for the next set bit | ||
28 | * If no bits are set, returns @size. | ||
29 | */ | ||
30 | extern unsigned long find_next_and_bit(const unsigned long *addr1, | ||
31 | const unsigned long *addr2, unsigned long size, | ||
32 | unsigned long offset); | ||
33 | #endif | ||
34 | |||
19 | #ifndef find_next_zero_bit | 35 | #ifndef find_next_zero_bit |
20 | /** | 36 | /** |
21 | * find_next_zero_bit - find the next cleared bit in a memory region | 37 | * find_next_zero_bit - find the next cleared bit in a memory region |
@@ -55,8 +71,12 @@ extern unsigned long find_first_zero_bit(const unsigned long *addr, | |||
55 | unsigned long size); | 71 | unsigned long size); |
56 | #else /* CONFIG_GENERIC_FIND_FIRST_BIT */ | 72 | #else /* CONFIG_GENERIC_FIND_FIRST_BIT */ |
57 | 73 | ||
74 | #ifndef find_first_bit | ||
58 | #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) | 75 | #define find_first_bit(addr, size) find_next_bit((addr), (size), 0) |
76 | #endif | ||
77 | #ifndef find_first_zero_bit | ||
59 | #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) | 78 | #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0) |
79 | #endif | ||
60 | 80 | ||
61 | #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ | 81 | #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */ |
62 | 82 | ||
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index d9bf699e0e7a..5f11fbdc27f8 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h | |||
@@ -88,8 +88,12 @@ | |||
88 | * test_and_change_bit(bit, addr) Change bit and return old value | 88 | * test_and_change_bit(bit, addr) Change bit and return old value |
89 | * find_first_zero_bit(addr, nbits) Position first zero bit in *addr | 89 | * find_first_zero_bit(addr, nbits) Position first zero bit in *addr |
90 | * find_first_bit(addr, nbits) Position first set bit in *addr | 90 | * find_first_bit(addr, nbits) Position first set bit in *addr |
91 | * find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit | 91 | * find_next_zero_bit(addr, nbits, bit) |
92 | * Position next zero bit in *addr >= bit | ||
92 | * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit | 93 | * find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit |
94 | * find_next_and_bit(addr1, addr2, nbits, bit) | ||
95 | * Same as find_next_bit, but in | ||
96 | * (*addr1 & *addr2) | ||
93 | * | 97 | * |
94 | */ | 98 | */ |
95 | 99 | ||
diff --git a/lib/cpumask.c b/lib/cpumask.c index 35fe142ebb5e..beca6244671a 100644 --- a/lib/cpumask.c +++ b/lib/cpumask.c | |||
@@ -33,10 +33,11 @@ EXPORT_SYMBOL(cpumask_next); | |||
33 | int cpumask_next_and(int n, const struct cpumask *src1p, | 33 | int cpumask_next_and(int n, const struct cpumask *src1p, |
34 | const struct cpumask *src2p) | 34 | const struct cpumask *src2p) |
35 | { | 35 | { |
36 | while ((n = cpumask_next(n, src1p)) < nr_cpu_ids) | 36 | /* -1 is a legal arg here. */ |
37 | if (cpumask_test_cpu(n, src2p)) | 37 | if (n != -1) |
38 | break; | 38 | cpumask_check(n); |
39 | return n; | 39 | return find_next_and_bit(cpumask_bits(src1p), cpumask_bits(src2p), |
40 | nr_cpumask_bits, n + 1); | ||
40 | } | 41 | } |
41 | EXPORT_SYMBOL(cpumask_next_and); | 42 | EXPORT_SYMBOL(cpumask_next_and); |
42 | 43 | ||
diff --git a/lib/find_bit.c b/lib/find_bit.c index 6ed74f78380c..ee3df93ba69a 100644 --- a/lib/find_bit.c +++ b/lib/find_bit.c | |||
@@ -21,22 +21,29 @@ | |||
21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | 23 | ||
24 | #if !defined(find_next_bit) || !defined(find_next_zero_bit) | 24 | #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ |
25 | !defined(find_next_and_bit) | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * This is a common helper function for find_next_bit and | 28 | * This is a common helper function for find_next_bit, find_next_zero_bit, and |
28 | * find_next_zero_bit. The difference is the "invert" argument, which | 29 | * find_next_and_bit. The differences are: |
29 | * is XORed with each fetched word before searching it for one bits. | 30 | * - The "invert" argument, which is XORed with each fetched word before |
31 | * searching it for one bits. | ||
32 | * - The optional "addr2", which is anded with "addr1" if present. | ||
30 | */ | 33 | */ |
31 | static unsigned long _find_next_bit(const unsigned long *addr, | 34 | static inline unsigned long _find_next_bit(const unsigned long *addr1, |
32 | unsigned long nbits, unsigned long start, unsigned long invert) | 35 | const unsigned long *addr2, unsigned long nbits, |
36 | unsigned long start, unsigned long invert) | ||
33 | { | 37 | { |
34 | unsigned long tmp; | 38 | unsigned long tmp; |
35 | 39 | ||
36 | if (unlikely(start >= nbits)) | 40 | if (unlikely(start >= nbits)) |
37 | return nbits; | 41 | return nbits; |
38 | 42 | ||
39 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 43 | tmp = addr1[start / BITS_PER_LONG]; |
44 | if (addr2) | ||
45 | tmp &= addr2[start / BITS_PER_LONG]; | ||
46 | tmp ^= invert; | ||
40 | 47 | ||
41 | /* Handle 1st word. */ | 48 | /* Handle 1st word. */ |
42 | tmp &= BITMAP_FIRST_WORD_MASK(start); | 49 | tmp &= BITMAP_FIRST_WORD_MASK(start); |
@@ -47,7 +54,10 @@ static unsigned long _find_next_bit(const unsigned long *addr, | |||
47 | if (start >= nbits) | 54 | if (start >= nbits) |
48 | return nbits; | 55 | return nbits; |
49 | 56 | ||
50 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 57 | tmp = addr1[start / BITS_PER_LONG]; |
58 | if (addr2) | ||
59 | tmp &= addr2[start / BITS_PER_LONG]; | ||
60 | tmp ^= invert; | ||
51 | } | 61 | } |
52 | 62 | ||
53 | return min(start + __ffs(tmp), nbits); | 63 | return min(start + __ffs(tmp), nbits); |
@@ -61,7 +71,7 @@ static unsigned long _find_next_bit(const unsigned long *addr, | |||
61 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 71 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, |
62 | unsigned long offset) | 72 | unsigned long offset) |
63 | { | 73 | { |
64 | return _find_next_bit(addr, size, offset, 0UL); | 74 | return _find_next_bit(addr, NULL, size, offset, 0UL); |
65 | } | 75 | } |
66 | EXPORT_SYMBOL(find_next_bit); | 76 | EXPORT_SYMBOL(find_next_bit); |
67 | #endif | 77 | #endif |
@@ -70,11 +80,21 @@ EXPORT_SYMBOL(find_next_bit); | |||
70 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, | 80 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, |
71 | unsigned long offset) | 81 | unsigned long offset) |
72 | { | 82 | { |
73 | return _find_next_bit(addr, size, offset, ~0UL); | 83 | return _find_next_bit(addr, NULL, size, offset, ~0UL); |
74 | } | 84 | } |
75 | EXPORT_SYMBOL(find_next_zero_bit); | 85 | EXPORT_SYMBOL(find_next_zero_bit); |
76 | #endif | 86 | #endif |
77 | 87 | ||
88 | #if !defined(find_next_and_bit) | ||
89 | unsigned long find_next_and_bit(const unsigned long *addr1, | ||
90 | const unsigned long *addr2, unsigned long size, | ||
91 | unsigned long offset) | ||
92 | { | ||
93 | return _find_next_bit(addr1, addr2, size, offset, 0UL); | ||
94 | } | ||
95 | EXPORT_SYMBOL(find_next_and_bit); | ||
96 | #endif | ||
97 | |||
78 | #ifndef find_first_bit | 98 | #ifndef find_first_bit |
79 | /* | 99 | /* |
80 | * Find the first set bit in a memory region. | 100 | * Find the first set bit in a memory region. |
@@ -146,15 +166,19 @@ static inline unsigned long ext2_swab(const unsigned long y) | |||
146 | } | 166 | } |
147 | 167 | ||
148 | #if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) | 168 | #if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le) |
149 | static unsigned long _find_next_bit_le(const unsigned long *addr, | 169 | static inline unsigned long _find_next_bit_le(const unsigned long *addr1, |
150 | unsigned long nbits, unsigned long start, unsigned long invert) | 170 | const unsigned long *addr2, unsigned long nbits, |
171 | unsigned long start, unsigned long invert) | ||
151 | { | 172 | { |
152 | unsigned long tmp; | 173 | unsigned long tmp; |
153 | 174 | ||
154 | if (unlikely(start >= nbits)) | 175 | if (unlikely(start >= nbits)) |
155 | return nbits; | 176 | return nbits; |
156 | 177 | ||
157 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 178 | tmp = addr1[start / BITS_PER_LONG]; |
179 | if (addr2) | ||
180 | tmp &= addr2[start / BITS_PER_LONG]; | ||
181 | tmp ^= invert; | ||
158 | 182 | ||
159 | /* Handle 1st word. */ | 183 | /* Handle 1st word. */ |
160 | tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); | 184 | tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start)); |
@@ -165,7 +189,10 @@ static unsigned long _find_next_bit_le(const unsigned long *addr, | |||
165 | if (start >= nbits) | 189 | if (start >= nbits) |
166 | return nbits; | 190 | return nbits; |
167 | 191 | ||
168 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 192 | tmp = addr1[start / BITS_PER_LONG]; |
193 | if (addr2) | ||
194 | tmp &= addr2[start / BITS_PER_LONG]; | ||
195 | tmp ^= invert; | ||
169 | } | 196 | } |
170 | 197 | ||
171 | return min(start + __ffs(ext2_swab(tmp)), nbits); | 198 | return min(start + __ffs(ext2_swab(tmp)), nbits); |
@@ -176,7 +203,7 @@ static unsigned long _find_next_bit_le(const unsigned long *addr, | |||
176 | unsigned long find_next_zero_bit_le(const void *addr, unsigned | 203 | unsigned long find_next_zero_bit_le(const void *addr, unsigned |
177 | long size, unsigned long offset) | 204 | long size, unsigned long offset) |
178 | { | 205 | { |
179 | return _find_next_bit_le(addr, size, offset, ~0UL); | 206 | return _find_next_bit_le(addr, NULL, size, offset, ~0UL); |
180 | } | 207 | } |
181 | EXPORT_SYMBOL(find_next_zero_bit_le); | 208 | EXPORT_SYMBOL(find_next_zero_bit_le); |
182 | #endif | 209 | #endif |
@@ -185,7 +212,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le); | |||
185 | unsigned long find_next_bit_le(const void *addr, unsigned | 212 | unsigned long find_next_bit_le(const void *addr, unsigned |
186 | long size, unsigned long offset) | 213 | long size, unsigned long offset) |
187 | { | 214 | { |
188 | return _find_next_bit_le(addr, size, offset, 0UL); | 215 | return _find_next_bit_le(addr, NULL, size, offset, 0UL); |
189 | } | 216 | } |
190 | EXPORT_SYMBOL(find_next_bit_le); | 217 | EXPORT_SYMBOL(find_next_bit_le); |
191 | #endif | 218 | #endif |
diff --git a/lib/find_bit_benchmark.c b/lib/find_bit_benchmark.c index 67b19233c28f..5985a25e6cbc 100644 --- a/lib/find_bit_benchmark.c +++ b/lib/find_bit_benchmark.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #define SPARSE 500 | 35 | #define SPARSE 500 |
36 | 36 | ||
37 | static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata; | 37 | static DECLARE_BITMAP(bitmap, BITMAP_LEN) __initdata; |
38 | static DECLARE_BITMAP(bitmap2, BITMAP_LEN) __initdata; | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * This is Schlemiel the Painter's algorithm. It should be called after | 41 | * This is Schlemiel the Painter's algorithm. It should be called after |
@@ -103,6 +104,22 @@ static int __init test_find_last_bit(const void *bitmap, unsigned long len) | |||
103 | return 0; | 104 | return 0; |
104 | } | 105 | } |
105 | 106 | ||
107 | static int __init test_find_next_and_bit(const void *bitmap, | ||
108 | const void *bitmap2, unsigned long len) | ||
109 | { | ||
110 | unsigned long i, cnt; | ||
111 | cycles_t cycles; | ||
112 | |||
113 | cycles = get_cycles(); | ||
114 | for (cnt = i = 0; i < BITMAP_LEN; cnt++) | ||
115 | i = find_next_and_bit(bitmap, bitmap2, BITMAP_LEN, i+1); | ||
116 | cycles = get_cycles() - cycles; | ||
117 | pr_err("find_next_and_bit:\t\t%llu cycles, %ld iterations\n", | ||
118 | (u64)cycles, cnt); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
106 | static int __init find_bit_test(void) | 123 | static int __init find_bit_test(void) |
107 | { | 124 | { |
108 | unsigned long nbits = BITMAP_LEN / SPARSE; | 125 | unsigned long nbits = BITMAP_LEN / SPARSE; |
@@ -110,23 +127,29 @@ static int __init find_bit_test(void) | |||
110 | pr_err("\nStart testing find_bit() with random-filled bitmap\n"); | 127 | pr_err("\nStart testing find_bit() with random-filled bitmap\n"); |
111 | 128 | ||
112 | get_random_bytes(bitmap, sizeof(bitmap)); | 129 | get_random_bytes(bitmap, sizeof(bitmap)); |
130 | get_random_bytes(bitmap2, sizeof(bitmap2)); | ||
113 | 131 | ||
114 | test_find_next_bit(bitmap, BITMAP_LEN); | 132 | test_find_next_bit(bitmap, BITMAP_LEN); |
115 | test_find_next_zero_bit(bitmap, BITMAP_LEN); | 133 | test_find_next_zero_bit(bitmap, BITMAP_LEN); |
116 | test_find_last_bit(bitmap, BITMAP_LEN); | 134 | test_find_last_bit(bitmap, BITMAP_LEN); |
117 | test_find_first_bit(bitmap, BITMAP_LEN); | 135 | test_find_first_bit(bitmap, BITMAP_LEN); |
136 | test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN); | ||
118 | 137 | ||
119 | pr_err("\nStart testing find_bit() with sparse bitmap\n"); | 138 | pr_err("\nStart testing find_bit() with sparse bitmap\n"); |
120 | 139 | ||
121 | bitmap_zero(bitmap, BITMAP_LEN); | 140 | bitmap_zero(bitmap, BITMAP_LEN); |
141 | bitmap_zero(bitmap2, BITMAP_LEN); | ||
122 | 142 | ||
123 | while (nbits--) | 143 | while (nbits--) { |
124 | __set_bit(prandom_u32() % BITMAP_LEN, bitmap); | 144 | __set_bit(prandom_u32() % BITMAP_LEN, bitmap); |
145 | __set_bit(prandom_u32() % BITMAP_LEN, bitmap2); | ||
146 | } | ||
125 | 147 | ||
126 | test_find_next_bit(bitmap, BITMAP_LEN); | 148 | test_find_next_bit(bitmap, BITMAP_LEN); |
127 | test_find_next_zero_bit(bitmap, BITMAP_LEN); | 149 | test_find_next_zero_bit(bitmap, BITMAP_LEN); |
128 | test_find_last_bit(bitmap, BITMAP_LEN); | 150 | test_find_last_bit(bitmap, BITMAP_LEN); |
129 | test_find_first_bit(bitmap, BITMAP_LEN); | 151 | test_find_first_bit(bitmap, BITMAP_LEN); |
152 | test_find_next_and_bit(bitmap, bitmap2, BITMAP_LEN); | ||
130 | 153 | ||
131 | /* | 154 | /* |
132 | * Everything is OK. Return error just to let user run benchmark | 155 | * Everything is OK. Return error just to let user run benchmark |
diff --git a/tools/include/asm-generic/bitops/find.h b/tools/include/asm-generic/bitops/find.h index 9311fadaaab2..16ed1982cb34 100644 --- a/tools/include/asm-generic/bitops/find.h +++ b/tools/include/asm-generic/bitops/find.h | |||
@@ -16,6 +16,22 @@ extern unsigned long find_next_bit(const unsigned long *addr, unsigned long | |||
16 | size, unsigned long offset); | 16 | size, unsigned long offset); |
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | #ifndef find_next_and_bit | ||
20 | /** | ||
21 | * find_next_and_bit - find the next set bit in both memory regions | ||
22 | * @addr1: The first address to base the search on | ||
23 | * @addr2: The second address to base the search on | ||
24 | * @offset: The bitnumber to start searching at | ||
25 | * @size: The bitmap size in bits | ||
26 | * | ||
27 | * Returns the bit number for the next set bit | ||
28 | * If no bits are set, returns @size. | ||
29 | */ | ||
30 | extern unsigned long find_next_and_bit(const unsigned long *addr1, | ||
31 | const unsigned long *addr2, unsigned long size, | ||
32 | unsigned long offset); | ||
33 | #endif | ||
34 | |||
19 | #ifndef find_next_zero_bit | 35 | #ifndef find_next_zero_bit |
20 | 36 | ||
21 | /** | 37 | /** |
diff --git a/tools/lib/find_bit.c b/tools/lib/find_bit.c index 42c15f906aac..a88bd507091e 100644 --- a/tools/lib/find_bit.c +++ b/tools/lib/find_bit.c | |||
@@ -22,22 +22,29 @@ | |||
22 | #include <linux/bitmap.h> | 22 | #include <linux/bitmap.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | 24 | ||
25 | #if !defined(find_next_bit) | 25 | #if !defined(find_next_bit) || !defined(find_next_zero_bit) || \ |
26 | !defined(find_next_and_bit) | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * This is a common helper function for find_next_bit and | 29 | * This is a common helper function for find_next_bit, find_next_zero_bit, and |
29 | * find_next_zero_bit. The difference is the "invert" argument, which | 30 | * find_next_and_bit. The differences are: |
30 | * is XORed with each fetched word before searching it for one bits. | 31 | * - The "invert" argument, which is XORed with each fetched word before |
32 | * searching it for one bits. | ||
33 | * - The optional "addr2", which is anded with "addr1" if present. | ||
31 | */ | 34 | */ |
32 | static unsigned long _find_next_bit(const unsigned long *addr, | 35 | static inline unsigned long _find_next_bit(const unsigned long *addr1, |
33 | unsigned long nbits, unsigned long start, unsigned long invert) | 36 | const unsigned long *addr2, unsigned long nbits, |
37 | unsigned long start, unsigned long invert) | ||
34 | { | 38 | { |
35 | unsigned long tmp; | 39 | unsigned long tmp; |
36 | 40 | ||
37 | if (unlikely(start >= nbits)) | 41 | if (unlikely(start >= nbits)) |
38 | return nbits; | 42 | return nbits; |
39 | 43 | ||
40 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 44 | tmp = addr1[start / BITS_PER_LONG]; |
45 | if (addr2) | ||
46 | tmp &= addr2[start / BITS_PER_LONG]; | ||
47 | tmp ^= invert; | ||
41 | 48 | ||
42 | /* Handle 1st word. */ | 49 | /* Handle 1st word. */ |
43 | tmp &= BITMAP_FIRST_WORD_MASK(start); | 50 | tmp &= BITMAP_FIRST_WORD_MASK(start); |
@@ -48,7 +55,10 @@ static unsigned long _find_next_bit(const unsigned long *addr, | |||
48 | if (start >= nbits) | 55 | if (start >= nbits) |
49 | return nbits; | 56 | return nbits; |
50 | 57 | ||
51 | tmp = addr[start / BITS_PER_LONG] ^ invert; | 58 | tmp = addr1[start / BITS_PER_LONG]; |
59 | if (addr2) | ||
60 | tmp &= addr2[start / BITS_PER_LONG]; | ||
61 | tmp ^= invert; | ||
52 | } | 62 | } |
53 | 63 | ||
54 | return min(start + __ffs(tmp), nbits); | 64 | return min(start + __ffs(tmp), nbits); |
@@ -62,7 +72,7 @@ static unsigned long _find_next_bit(const unsigned long *addr, | |||
62 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 72 | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, |
63 | unsigned long offset) | 73 | unsigned long offset) |
64 | { | 74 | { |
65 | return _find_next_bit(addr, size, offset, 0UL); | 75 | return _find_next_bit(addr, NULL, size, offset, 0UL); |
66 | } | 76 | } |
67 | #endif | 77 | #endif |
68 | 78 | ||
@@ -104,6 +114,15 @@ unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) | |||
104 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, | 114 | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, |
105 | unsigned long offset) | 115 | unsigned long offset) |
106 | { | 116 | { |
107 | return _find_next_bit(addr, size, offset, ~0UL); | 117 | return _find_next_bit(addr, NULL, size, offset, ~0UL); |
118 | } | ||
119 | #endif | ||
120 | |||
121 | #ifndef find_next_and_bit | ||
122 | unsigned long find_next_and_bit(const unsigned long *addr1, | ||
123 | const unsigned long *addr2, unsigned long size, | ||
124 | unsigned long offset) | ||
125 | { | ||
126 | return _find_next_bit(addr1, addr2, size, offset, 0UL); | ||
108 | } | 127 | } |
109 | #endif | 128 | #endif |