#include #define BITS_PER_LONG 64 #define ffz(x) __ffs(~(x)) #define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) static __always_inline unsigned long __ffs(unsigned long word) { int num = 0; #if BITS_PER_LONG == 64 if ((word & 0xffffffff) == 0) { num += 32; word >>= 32; } #endif if ((word & 0xffff) == 0) { num += 16; word >>= 16; } if ((word & 0xff) == 0) { num += 8; word >>= 8; } if ((word & 0xf) == 0) { num += 4; word >>= 4; } if ((word & 0x3) == 0) { num += 2; word >>= 2; } if ((word & 0x1) == 0) num += 1; return num; } static inline void set_bit(int nr, volatile unsigned long *addr) { unsigned long mask = BIT_MASK(nr); unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr); unsigned long flags; *p |= mask; } unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) { const unsigned long *p = addr; unsigned long result = 0; unsigned long tmp; while (size & ~(BITS_PER_LONG-1)) { if (~(tmp = *(p++))) goto found; result += BITS_PER_LONG; size -= BITS_PER_LONG; } if (!size) return result; tmp = (*p) | (~0UL << size); if (tmp == ~0UL) /* Are any bits zero? */ return result + size; /* Nope. */ found: return result + ffz(tmp); } int main() { unsigned long a[1] = {0x0UL}; unsigned long index; index = find_first_zero_bit(a, 64); printf("%lu\n", 64-index-1 ); set_bit( 0, a ); index = find_first_zero_bit(a, 64); printf("%lu\n", 64-index-1 ); return 0; }