|
@@ -21,22 +21,29 @@
|
|
|
#include <linux/export.h>
|
|
|
#include <linux/kernel.h>
|
|
|
|
|
|
-#if !defined(find_next_bit) || !defined(find_next_zero_bit)
|
|
|
+#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
|
|
|
+ !defined(find_next_and_bit)
|
|
|
|
|
|
/*
|
|
|
- * This is a common helper function for find_next_bit and
|
|
|
- * find_next_zero_bit. The difference is the "invert" argument, which
|
|
|
- * is XORed with each fetched word before searching it for one bits.
|
|
|
+ * This is a common helper function for find_next_bit, find_next_zero_bit, and
|
|
|
+ * find_next_and_bit. The differences are:
|
|
|
+ * - The "invert" argument, which is XORed with each fetched word before
|
|
|
+ * searching it for one bits.
|
|
|
+ * - The optional "addr2", which is anded with "addr1" if present.
|
|
|
*/
|
|
|
-static unsigned long _find_next_bit(const unsigned long *addr,
|
|
|
- unsigned long nbits, unsigned long start, unsigned long invert)
|
|
|
+static inline unsigned long _find_next_bit(const unsigned long *addr1,
|
|
|
+ const unsigned long *addr2, unsigned long nbits,
|
|
|
+ unsigned long start, unsigned long invert)
|
|
|
{
|
|
|
unsigned long tmp;
|
|
|
|
|
|
if (unlikely(start >= nbits))
|
|
|
return nbits;
|
|
|
|
|
|
- tmp = addr[start / BITS_PER_LONG] ^ invert;
|
|
|
+ tmp = addr1[start / BITS_PER_LONG];
|
|
|
+ if (addr2)
|
|
|
+ tmp &= addr2[start / BITS_PER_LONG];
|
|
|
+ tmp ^= invert;
|
|
|
|
|
|
/* Handle 1st word. */
|
|
|
tmp &= BITMAP_FIRST_WORD_MASK(start);
|
|
@@ -47,7 +54,10 @@ static unsigned long _find_next_bit(const unsigned long *addr,
|
|
|
if (start >= nbits)
|
|
|
return nbits;
|
|
|
|
|
|
- tmp = addr[start / BITS_PER_LONG] ^ invert;
|
|
|
+ tmp = addr1[start / BITS_PER_LONG];
|
|
|
+ if (addr2)
|
|
|
+ tmp &= addr2[start / BITS_PER_LONG];
|
|
|
+ tmp ^= invert;
|
|
|
}
|
|
|
|
|
|
return min(start + __ffs(tmp), nbits);
|
|
@@ -61,7 +71,7 @@ static unsigned long _find_next_bit(const unsigned long *addr,
|
|
|
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
|
|
unsigned long offset)
|
|
|
{
|
|
|
- return _find_next_bit(addr, size, offset, 0UL);
|
|
|
+ return _find_next_bit(addr, NULL, size, offset, 0UL);
|
|
|
}
|
|
|
EXPORT_SYMBOL(find_next_bit);
|
|
|
#endif
|
|
@@ -70,11 +80,21 @@ EXPORT_SYMBOL(find_next_bit);
|
|
|
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
|
|
unsigned long offset)
|
|
|
{
|
|
|
- return _find_next_bit(addr, size, offset, ~0UL);
|
|
|
+ return _find_next_bit(addr, NULL, size, offset, ~0UL);
|
|
|
}
|
|
|
EXPORT_SYMBOL(find_next_zero_bit);
|
|
|
#endif
|
|
|
|
|
|
+#if !defined(find_next_and_bit)
|
|
|
+unsigned long find_next_and_bit(const unsigned long *addr1,
|
|
|
+ const unsigned long *addr2, unsigned long size,
|
|
|
+ unsigned long offset)
|
|
|
+{
|
|
|
+ return _find_next_bit(addr1, addr2, size, offset, 0UL);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(find_next_and_bit);
|
|
|
+#endif
|
|
|
+
|
|
|
#ifndef find_first_bit
|
|
|
/*
|
|
|
* Find the first set bit in a memory region.
|
|
@@ -146,15 +166,19 @@ static inline unsigned long ext2_swab(const unsigned long y)
|
|
|
}
|
|
|
|
|
|
#if !defined(find_next_bit_le) || !defined(find_next_zero_bit_le)
|
|
|
-static unsigned long _find_next_bit_le(const unsigned long *addr,
|
|
|
- unsigned long nbits, unsigned long start, unsigned long invert)
|
|
|
+static inline unsigned long _find_next_bit_le(const unsigned long *addr1,
|
|
|
+ const unsigned long *addr2, unsigned long nbits,
|
|
|
+ unsigned long start, unsigned long invert)
|
|
|
{
|
|
|
unsigned long tmp;
|
|
|
|
|
|
if (unlikely(start >= nbits))
|
|
|
return nbits;
|
|
|
|
|
|
- tmp = addr[start / BITS_PER_LONG] ^ invert;
|
|
|
+ tmp = addr1[start / BITS_PER_LONG];
|
|
|
+ if (addr2)
|
|
|
+ tmp &= addr2[start / BITS_PER_LONG];
|
|
|
+ tmp ^= invert;
|
|
|
|
|
|
/* Handle 1st word. */
|
|
|
tmp &= ext2_swab(BITMAP_FIRST_WORD_MASK(start));
|
|
@@ -165,7 +189,10 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
|
|
|
if (start >= nbits)
|
|
|
return nbits;
|
|
|
|
|
|
- tmp = addr[start / BITS_PER_LONG] ^ invert;
|
|
|
+ tmp = addr1[start / BITS_PER_LONG];
|
|
|
+ if (addr2)
|
|
|
+ tmp &= addr2[start / BITS_PER_LONG];
|
|
|
+ tmp ^= invert;
|
|
|
}
|
|
|
|
|
|
return min(start + __ffs(ext2_swab(tmp)), nbits);
|
|
@@ -176,7 +203,7 @@ static unsigned long _find_next_bit_le(const unsigned long *addr,
|
|
|
unsigned long find_next_zero_bit_le(const void *addr, unsigned
|
|
|
long size, unsigned long offset)
|
|
|
{
|
|
|
- return _find_next_bit_le(addr, size, offset, ~0UL);
|
|
|
+ return _find_next_bit_le(addr, NULL, size, offset, ~0UL);
|
|
|
}
|
|
|
EXPORT_SYMBOL(find_next_zero_bit_le);
|
|
|
#endif
|
|
@@ -185,7 +212,7 @@ EXPORT_SYMBOL(find_next_zero_bit_le);
|
|
|
unsigned long find_next_bit_le(const void *addr, unsigned
|
|
|
long size, unsigned long offset)
|
|
|
{
|
|
|
- return _find_next_bit_le(addr, size, offset, 0UL);
|
|
|
+ return _find_next_bit_le(addr, NULL, size, offset, 0UL);
|
|
|
}
|
|
|
EXPORT_SYMBOL(find_next_bit_le);
|
|
|
#endif
|