X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=include%2Fasm-arm%2Fbitops.h;h=d02de721ecc185cdcfcbe6f5e707083c477e5413;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=0ac54b1a8bad7c0e8e7a7a3ec8f5063d6c972732;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h index 0ac54b1a8..d02de721e 100644 --- a/include/asm-arm/bitops.h +++ b/include/asm-arm/bitops.h @@ -117,7 +117,65 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p) return res & mask; } -#include +/* + * Now the non-atomic variants. We let the compiler handle all + * optimisations for these. These are all _native_ endian. + */ +static inline void __set_bit(int nr, volatile unsigned long *p) +{ + p[nr >> 5] |= (1UL << (nr & 31)); +} + +static inline void __clear_bit(int nr, volatile unsigned long *p) +{ + p[nr >> 5] &= ~(1UL << (nr & 31)); +} + +static inline void __change_bit(int nr, volatile unsigned long *p) +{ + p[nr >> 5] ^= (1UL << (nr & 31)); +} + +static inline int __test_and_set_bit(int nr, volatile unsigned long *p) +{ + unsigned long oldval, mask = 1UL << (nr & 31); + + p += nr >> 5; + + oldval = *p; + *p = oldval | mask; + return oldval & mask; +} + +static inline int __test_and_clear_bit(int nr, volatile unsigned long *p) +{ + unsigned long oldval, mask = 1UL << (nr & 31); + + p += nr >> 5; + + oldval = *p; + *p = oldval & ~mask; + return oldval & mask; +} + +static inline int __test_and_change_bit(int nr, volatile unsigned long *p) +{ + unsigned long oldval, mask = 1UL << (nr & 31); + + p += nr >> 5; + + oldval = *p; + *p = oldval ^ mask; + return oldval & mask; +} + +/* + * This routine doesn't need to be atomic. + */ +static inline int __test_bit(int nr, const volatile unsigned long * p) +{ + return (p[nr >> 5] >> (nr & 31)) & 1UL; +} /* * A note about Endian-ness. @@ -203,6 +261,7 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define test_and_set_bit(nr,p) ATOMIC_BITOP_LE(test_and_set_bit,nr,p) #define test_and_clear_bit(nr,p) ATOMIC_BITOP_LE(test_and_clear_bit,nr,p) #define test_and_change_bit(nr,p) ATOMIC_BITOP_LE(test_and_change_bit,nr,p) +#define test_bit(nr,p) __test_bit(nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_le(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_le(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_le(p,sz) @@ -221,6 +280,7 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #define test_and_set_bit(nr,p) ATOMIC_BITOP_BE(test_and_set_bit,nr,p) #define test_and_clear_bit(nr,p) ATOMIC_BITOP_BE(test_and_clear_bit,nr,p) #define test_and_change_bit(nr,p) ATOMIC_BITOP_BE(test_and_change_bit,nr,p) +#define test_bit(nr,p) __test_bit(nr,p) #define find_first_zero_bit(p,sz) _find_first_zero_bit_be(p,sz) #define find_next_zero_bit(p,sz,off) _find_next_zero_bit_be(p,sz,off) #define find_first_bit(p,sz) _find_first_bit_be(p,sz) @@ -232,60 +292,97 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset); #if __LINUX_ARM_ARCH__ < 5 -#include -#include -#include -#include - -#else - -static inline int constant_fls(int x) +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +static inline unsigned long ffz(unsigned long word) { - int r = 32; + int k; + + word = ~word; + k = 31; + if (word & 0x0000ffff) { k -= 16; word <<= 16; } + if (word & 0x00ff0000) { k -= 8; word <<= 8; } + if (word & 0x0f000000) { k -= 4; word <<= 4; } + if (word & 0x30000000) { k -= 2; word <<= 2; } + if (word & 0x40000000) { k -= 1; } + return k; +} - if (!x) - return 0; - if (!(x & 0xffff0000u)) { - x <<= 16; - r -= 16; - } - if (!(x & 0xff000000u)) { - x <<= 8; - r -= 8; - } - if (!(x & 0xf0000000u)) { - x <<= 4; - r -= 4; - } - if (!(x & 0xc0000000u)) { - x <<= 2; - r -= 2; - } - if (!(x & 0x80000000u)) { - x <<= 1; - r -= 1; - } - return r; +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +static inline unsigned long __ffs(unsigned long word) +{ + int k; + + k = 31; + if (word & 0x0000ffff) { k -= 16; word <<= 16; } + if (word & 0x00ff0000) { k -= 8; word <<= 8; } + if (word & 0x0f000000) { k -= 4; word <<= 4; } + if (word & 0x30000000) { k -= 2; word <<= 2; } + if (word & 0x40000000) { k -= 1; } + return k; } +/* + * fls: find last bit set. + */ + +#define fls(x) generic_fls(x) +#define fls64(x) generic_fls64(x) + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +#else + /* * On ARMv5 and above those functions can be implemented around * the clz instruction for much better code efficiency. */ #define fls(x) \ - ( __builtin_constant_p(x) ? constant_fls(x) : \ + ( __builtin_constant_p(x) ? generic_fls(x) : \ ({ int __r; asm("clz\t%0, %1" : "=r"(__r) : "r"(x) : "cc"); 32-__r; }) ) +#define fls64(x) generic_fls64(x) #define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); }) #define __ffs(x) (ffs(x) - 1) #define ffz(x) __ffs( ~(x) ) #endif -#include +/* + * Find first bit set in a 168-bit bitmap, where the first + * 128 bits are unlikely to be set. + */ +static inline int sched_find_first_bit(const unsigned long *b) +{ + unsigned long v; + unsigned int off; + + for (off = 0; v = b[off], off < 4; off++) { + if (unlikely(v)) + break; + } + return __ffs(v) + off * 32; +} + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ -#include -#include +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) /* * Ext2 is defined to use little-endian byte ordering. @@ -300,7 +397,7 @@ static inline int constant_fls(int x) #define ext2_clear_bit_atomic(lock,nr,p) \ test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define ext2_test_bit(nr,p) \ - test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) + __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define ext2_find_first_zero_bit(p,sz) \ _find_first_zero_bit_le(p,sz) #define ext2_find_next_zero_bit(p,sz,off) \ @@ -313,7 +410,7 @@ static inline int constant_fls(int x) #define minix_set_bit(nr,p) \ __set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define minix_test_bit(nr,p) \ - test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) + __test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define minix_test_and_set_bit(nr,p) \ __test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p)) #define minix_test_and_clear_bit(nr,p) \