aboutsummaryrefslogtreecommitdiffstats
path: root/lib/find_bit.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/find_bit.c')
-rw-r--r--lib/find_bit.c59
1 files changed, 43 insertions, 16 deletions
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 */
31static unsigned long _find_next_bit(const unsigned long *addr, 34static 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,
61unsigned long find_next_bit(const unsigned long *addr, unsigned long size, 71unsigned 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}
66EXPORT_SYMBOL(find_next_bit); 76EXPORT_SYMBOL(find_next_bit);
67#endif 77#endif
@@ -70,11 +80,21 @@ EXPORT_SYMBOL(find_next_bit);
70unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, 80unsigned 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}
75EXPORT_SYMBOL(find_next_zero_bit); 85EXPORT_SYMBOL(find_next_zero_bit);
76#endif 86#endif
77 87
88#if !defined(find_next_and_bit)
89unsigned 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}
95EXPORT_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)
149static unsigned long _find_next_bit_le(const unsigned long *addr, 169static 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,
176unsigned long find_next_zero_bit_le(const void *addr, unsigned 203unsigned 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}
181EXPORT_SYMBOL(find_next_zero_bit_le); 208EXPORT_SYMBOL(find_next_zero_bit_le);
182#endif 209#endif
@@ -185,7 +212,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le);
185unsigned long find_next_bit_le(const void *addr, unsigned 212unsigned 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}
190EXPORT_SYMBOL(find_next_bit_le); 217EXPORT_SYMBOL(find_next_bit_le);
191#endif 218#endif