at v2.6.25 4.0 kB view raw
1#ifndef _I386_SYNC_BITOPS_H 2#define _I386_SYNC_BITOPS_H 3 4/* 5 * Copyright 1992, Linus Torvalds. 6 */ 7 8/* 9 * These have to be done with inline assembly: that way the bit-setting 10 * is guaranteed to be atomic. All bit operations return 0 if the bit 11 * was cleared before the operation and != 0 if it was not. 12 * 13 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). 14 */ 15 16#define ADDR (*(volatile long *) addr) 17 18/** 19 * sync_set_bit - Atomically set a bit in memory 20 * @nr: the bit to set 21 * @addr: the address to start counting from 22 * 23 * This function is atomic and may not be reordered. See __set_bit() 24 * if you do not require the atomic guarantees. 25 * 26 * Note that @nr may be almost arbitrarily large; this function is not 27 * restricted to acting on a single-word quantity. 28 */ 29static inline void sync_set_bit(int nr, volatile unsigned long * addr) 30{ 31 __asm__ __volatile__("lock; btsl %1,%0" 32 :"+m" (ADDR) 33 :"Ir" (nr) 34 : "memory"); 35} 36 37/** 38 * sync_clear_bit - Clears a bit in memory 39 * @nr: Bit to clear 40 * @addr: Address to start counting from 41 * 42 * sync_clear_bit() is atomic and may not be reordered. However, it does 43 * not contain a memory barrier, so if it is used for locking purposes, 44 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() 45 * in order to ensure changes are visible on other processors. 46 */ 47static inline void sync_clear_bit(int nr, volatile unsigned long * addr) 48{ 49 __asm__ __volatile__("lock; btrl %1,%0" 50 :"+m" (ADDR) 51 :"Ir" (nr) 52 : "memory"); 53} 54 55/** 56 * sync_change_bit - Toggle a bit in memory 57 * @nr: Bit to change 58 * @addr: Address to start counting from 59 * 60 * sync_change_bit() is atomic and may not be reordered. 61 * Note that @nr may be almost arbitrarily large; this function is not 62 * restricted to acting on a single-word quantity. 63 */ 64static inline void sync_change_bit(int nr, volatile unsigned long * addr) 65{ 66 __asm__ __volatile__("lock; btcl %1,%0" 67 :"+m" (ADDR) 68 :"Ir" (nr) 69 : "memory"); 70} 71 72/** 73 * sync_test_and_set_bit - Set a bit and return its old value 74 * @nr: Bit to set 75 * @addr: Address to count from 76 * 77 * This operation is atomic and cannot be reordered. 78 * It also implies a memory barrier. 79 */ 80static inline int sync_test_and_set_bit(int nr, volatile unsigned long * addr) 81{ 82 int oldbit; 83 84 __asm__ __volatile__("lock; btsl %2,%1\n\tsbbl %0,%0" 85 :"=r" (oldbit),"+m" (ADDR) 86 :"Ir" (nr) : "memory"); 87 return oldbit; 88} 89 90/** 91 * sync_test_and_clear_bit - Clear a bit and return its old value 92 * @nr: Bit to clear 93 * @addr: Address to count from 94 * 95 * This operation is atomic and cannot be reordered. 96 * It also implies a memory barrier. 97 */ 98static inline int sync_test_and_clear_bit(int nr, volatile unsigned long * addr) 99{ 100 int oldbit; 101 102 __asm__ __volatile__("lock; btrl %2,%1\n\tsbbl %0,%0" 103 :"=r" (oldbit),"+m" (ADDR) 104 :"Ir" (nr) : "memory"); 105 return oldbit; 106} 107 108/** 109 * sync_test_and_change_bit - Change a bit and return its old value 110 * @nr: Bit to change 111 * @addr: Address to count from 112 * 113 * This operation is atomic and cannot be reordered. 114 * It also implies a memory barrier. 115 */ 116static inline int sync_test_and_change_bit(int nr, volatile unsigned long* addr) 117{ 118 int oldbit; 119 120 __asm__ __volatile__("lock; btcl %2,%1\n\tsbbl %0,%0" 121 :"=r" (oldbit),"+m" (ADDR) 122 :"Ir" (nr) : "memory"); 123 return oldbit; 124} 125 126static __always_inline int sync_constant_test_bit(int nr, const volatile unsigned long *addr) 127{ 128 return ((1UL << (nr & 31)) & 129 (((const volatile unsigned int *)addr)[nr >> 5])) != 0; 130} 131 132static inline int sync_var_test_bit(int nr, const volatile unsigned long * addr) 133{ 134 int oldbit; 135 136 __asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0" 137 :"=r" (oldbit) 138 :"m" (ADDR),"Ir" (nr)); 139 return oldbit; 140} 141 142#define sync_test_bit(nr,addr) \ 143 (__builtin_constant_p(nr) ? \ 144 sync_constant_test_bit((nr),(addr)) : \ 145 sync_var_test_bit((nr),(addr))) 146 147#undef ADDR 148 149#endif /* _I386_SYNC_BITOPS_H */