X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Ffind_next_bit.c;fp=lib%2Ffind_next_bit.c;h=c05b4b19cf6cac90e407eac98e870130bbb3e66a;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=bda0d71a25144c110df24920b6320470e9c213a8;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c index bda0d71a2..c05b4b19c 100644 --- a/lib/find_next_bit.c +++ b/lib/find_next_bit.c @@ -11,171 +11,48 @@ #include #include -#include -#include -#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) - -/** - * find_next_bit - find the next set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -unsigned long find_next_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) +int find_next_bit(const unsigned long *addr, int size, int offset) { - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); + const unsigned long *base; + const int NBITS = sizeof(*addr) * 8; unsigned long tmp; - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; + base = addr; if (offset) { - tmp = *(p++); - tmp &= (~0UL << offset); - if (size < BITS_PER_LONG) - goto found_first; - if (tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if ((tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; - } - if (!size) - return result; - tmp = *p; + int suboffset; -found_first: - tmp &= (~0UL >> (BITS_PER_LONG - size)); - if (tmp == 0UL) /* Are any bits set? */ - return result + size; /* Nope. */ -found_middle: - return result + __ffs(tmp); -} + addr += offset / NBITS; -EXPORT_SYMBOL(find_next_bit); + suboffset = offset % NBITS; + if (suboffset) { + tmp = *addr; + tmp >>= suboffset; + if (tmp) + goto finish; + } -/* - * This implementation of find_{first,next}_zero_bit was stolen from - * Linus' asm-alpha/bitops.h. - */ -unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, - unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG-1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset %= BITS_PER_LONG; - if (offset) { - tmp = *(p++); - tmp |= ~0UL >> (BITS_PER_LONG - offset); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; - } - while (size & ~(BITS_PER_LONG-1)) { - if (~(tmp = *(p++))) - goto found_middle; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + addr++; } - if (!size) - return result; - tmp = *p; - -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. */ -found_middle: - return result + ffz(tmp); -} - -EXPORT_SYMBOL(find_next_zero_bit); -#ifdef __BIG_ENDIAN + while ((tmp = *addr) == 0) + addr++; -/* include/linux/byteorder does not support "unsigned long" type */ -static inline unsigned long ext2_swabp(const unsigned long * x) -{ -#if BITS_PER_LONG == 64 - return (unsigned long) __swab64p((u64 *) x); -#elif BITS_PER_LONG == 32 - return (unsigned long) __swab32p((u32 *) x); -#else -#error BITS_PER_LONG not defined -#endif -} - -/* include/linux/byteorder doesn't support "unsigned long" type */ -static inline unsigned long ext2_swab(const unsigned long y) -{ -#if BITS_PER_LONG == 64 - return (unsigned long) __swab64((u64) y); -#elif BITS_PER_LONG == 32 - return (unsigned long) __swab32((u32) y); -#else -#error BITS_PER_LONG not defined -#endif -} + offset = (addr - base) * NBITS; -unsigned long generic_find_next_zero_le_bit(const unsigned long *addr, unsigned - long size, unsigned long offset) -{ - const unsigned long *p = addr + BITOP_WORD(offset); - unsigned long result = offset & ~(BITS_PER_LONG - 1); - unsigned long tmp; - - if (offset >= size) - return size; - size -= result; - offset &= (BITS_PER_LONG - 1UL); - if (offset) { - tmp = ext2_swabp(p++); - tmp |= (~0UL >> (BITS_PER_LONG - offset)); - if (size < BITS_PER_LONG) - goto found_first; - if (~tmp) - goto found_middle; - size -= BITS_PER_LONG; - result += BITS_PER_LONG; + finish: + /* count the remaining bits without using __ffs() since that takes a 32-bit arg */ + while (!(tmp & 0xff)) { + offset += 8; + tmp >>= 8; } - while (size & ~(BITS_PER_LONG - 1)) { - if (~(tmp = *(p++))) - goto found_middle_swap; - result += BITS_PER_LONG; - size -= BITS_PER_LONG; + while (!(tmp & 1)) { + offset++; + tmp >>= 1; } - if (!size) - return result; - tmp = ext2_swabp(p); -found_first: - tmp |= ~0UL << size; - if (tmp == ~0UL) /* Are any bits zero? */ - return result + size; /* Nope. Skip ffz */ -found_middle: - return result + ffz(tmp); -found_middle_swap: - return result + ffz(ext2_swab(tmp)); + return offset; } -EXPORT_SYMBOL(generic_find_next_zero_le_bit); - -#endif /* __BIG_ENDIAN */ +EXPORT_SYMBOL(find_next_bit);