Index: linux-2.6.16-mm2/include/asm-ia64/bitops.h =================================================================== --- linux-2.6.16-mm2.orig/include/asm-ia64/bitops.h 2006-03-30 12:12:33.000000000 -0800 +++ linux-2.6.16-mm2/include/asm-ia64/bitops.h 2006-03-30 12:12:43.000000000 -0800 @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -19,8 +20,6 @@ * @nr: the bit to set * @addr: the address to start counting from * - * This function is atomic and may not be reordered. See __set_bit() - * if you do not require the atomic guarantees. * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. * @@ -34,244 +33,106 @@ static __inline__ void set_bit (int nr, volatile void *addr) { - __u32 bit, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - bit = 1 << (nr & 31); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old | bit; - } while (cmpxchg_acq(m, old, new) != old); + set_bit_mode(nr, addr, MODE_ATOMIC); } /** * __set_bit - Set a bit in memory * @nr: the bit to set * @addr: the address to start counting from - * - * Unlike set_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. */ static __inline__ void __set_bit (int nr, volatile void *addr) { - *((__u32 *) addr + (nr >> 5)) |= (1 << (nr & 31)); + set_bit_mode(nr, addr, MODE_NON_ATOMIC); } -/* - * clear_bit() has "acquire" semantics. - */ #define smp_mb__before_clear_bit() smp_mb() -#define smp_mb__after_clear_bit() do { /* skip */; } while (0) +#define smp_mb__after_clear_bit() smb_mb() /** * clear_bit - Clears a bit in memory * @nr: Bit to clear * @addr: Address to start counting from - * - * clear_bit() is atomic and may not be reordered. However, it does - * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() - * in order to ensure changes are visible on other processors. */ static __inline__ void clear_bit (int nr, volatile void *addr) { - __u32 mask, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - mask = ~(1 << (nr & 31)); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old & mask; - } while (cmpxchg_acq(m, old, new) != old); + clear_bit_mode(nr, addr, MODE_ATOMIC); } -/** - * __clear_bit - Clears a bit in memory (non-atomic version) - */ static __inline__ void __clear_bit (int nr, volatile void *addr) { - volatile __u32 *p = (__u32 *) addr + (nr >> 5); - __u32 m = 1 << (nr & 31); - *p &= ~m; + clear_bit_mode(nr, addr, MODE_NON_ATOMIC); } /** * change_bit - Toggle a bit in memory * @nr: Bit to clear * @addr: Address to start counting from - * - * change_bit() is atomic and may not be reordered. - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. */ static __inline__ void change_bit (int nr, volatile void *addr) { - __u32 bit, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - bit = (1 << (nr & 31)); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old ^ bit; - } while (cmpxchg_acq(m, old, new) != old); + change_bit_mode(nr, addr, MODE_ATOMIC); } -/** - * __change_bit - Toggle a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * Unlike change_bit(), this function is non-atomic and may be reordered. - * If it's called on the same region of memory simultaneously, the effect - * may be that only one operation succeeds. - */ static __inline__ void __change_bit (int nr, volatile void *addr) { - *((__u32 *) addr + (nr >> 5)) ^= (1 << (nr & 31)); + change_bit_mode(nr, addr, MODE_NON_ATOMIC); } /** * test_and_set_bit - Set a bit and return its old value * @nr: Bit to set * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. */ static __inline__ int test_and_set_bit (int nr, volatile void *addr) { - __u32 bit, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - bit = 1 << (nr & 31); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old | bit; - } while (cmpxchg_acq(m, old, new) != old); - return (old & bit) != 0; + return test_and_set_bit_mode(nr, addr, MODE_ATOMIC); } -/** - * __test_and_set_bit - Set a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ static __inline__ int __test_and_set_bit (int nr, volatile void *addr) { - __u32 *p = (__u32 *) addr + (nr >> 5); - __u32 m = 1 << (nr & 31); - int oldbitset = (*p & m) != 0; - - *p |= m; - return oldbitset; + return test_and_set_bit_mode(nr, addr, MODE_NON_ATOMIC); } /** * test_and_clear_bit - Clear a bit and return its old value * @nr: Bit to set * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. */ static __inline__ int test_and_clear_bit (int nr, volatile void *addr) { - __u32 mask, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - mask = ~(1 << (nr & 31)); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old & mask; - } while (cmpxchg_acq(m, old, new) != old); - return (old & ~mask) != 0; + return test_and_clear_bit_mode(nr, addr, MODE_ATOMIC); } -/** - * __test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is non-atomic and can be reordered. - * If two examples of this operation race, one can appear to succeed - * but actually fail. You must protect multiple accesses with a lock. - */ static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) { - __u32 *p = (__u32 *) addr + (nr >> 5); - __u32 m = 1 << (nr & 31); - int oldbitset = *p & m; - - *p &= ~m; - return oldbitset; + return test_and_clear_bit_mode(nr, addr, MODE_NON_ATOMIC); } /** * test_and_change_bit - Change a bit and return its old value * @nr: Bit to set * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. */ static __inline__ int test_and_change_bit (int nr, volatile void *addr) { - __u32 bit, old, new; - volatile __u32 *m; - CMPXCHG_BUGCHECK_DECL - - m = (volatile __u32 *) addr + (nr >> 5); - bit = (1 << (nr & 31)); - do { - CMPXCHG_BUGCHECK(m); - old = *m; - new = old ^ bit; - } while (cmpxchg_acq(m, old, new) != old); - return (old & bit) != 0; + return test_and_change_bit_mode(nr, addr, MODE_ATOMIC); } -/* - * WARNING: non atomic version. - */ static __inline__ int __test_and_change_bit (int nr, void *addr) { - __u32 old, bit = (1 << (nr & 31)); - __u32 *m = (__u32 *) addr + (nr >> 5); - - old = *m; - *m = old ^ bit; - return (old & bit) != 0; + return test_and_change_bit_mode(nr, addr, MODE_NON_ATOMIC); } static __inline__ int