1 #ifndef __LINUX_BIT_SPINLOCK_H 2 #define __LINUX_BIT_SPINLOCK_H 3 4 #include <linux/kernel.h> 5 #include <linux/preempt.h> 6 #include <asm/atomic.h> 7 8 /* 9 * bit-based spin_lock() 10 * 11 * Don't use this unless you really need to: spin_lock() and spin_unlock() 12 * are significantly faster. 13 */ 14 static inline void bit_spin_lock(int bitnum, unsigned long *addr) 15 { 16 /* 17 * Assuming the lock is uncontended, this never enters 18 * the body of the outer loop. If it is contended, then 19 * within the inner loop a non-atomic test is used to 20 * busywait with less bus contention for a good time to 21 * attempt to acquire the lock bit. 22 */ 23 preempt_disable(); 24 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 25 while (unlikely(test_and_set_bit_lock(bitnum, addr))) { 26 preempt_enable(); 27 do { 28 cpu_relax(); 29 } while (test_bit(bitnum, addr)); 30 preempt_disable(); 31 } 32 #endif 33 __acquire(bitlock); 34 } 35 36 /* 37 * Return true if it was acquired 38 */ 39 static inline int bit_spin_trylock(int bitnum, unsigned long *addr) 40 { 41 preempt_disable(); 42 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 43 if (unlikely(test_and_set_bit_lock(bitnum, addr))) { 44 preempt_enable(); 45 return 0; 46 } 47 #endif 48 __acquire(bitlock); 49 return 1; 50 } 51 52 /* 53 * bit-based spin_unlock() 54 */ 55 static inline void bit_spin_unlock(int bitnum, unsigned long *addr) 56 { 57 #ifdef CONFIG_DEBUG_SPINLOCK 58 BUG_ON(!test_bit(bitnum, addr)); 59 #endif 60 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 61 clear_bit_unlock(bitnum, addr); 62 #endif 63 preempt_enable(); 64 __release(bitlock); 65 } 66 67 /* 68 * bit-based spin_unlock() 69 * non-atomic version, which can be used eg. if the bit lock itself is 70 * protecting the rest of the flags in the word. 71 */ 72 static inline void __bit_spin_unlock(int bitnum, unsigned long *addr) 73 { 74 #ifdef CONFIG_DEBUG_SPINLOCK 75 BUG_ON(!test_bit(bitnum, addr)); 76 #endif 77 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 78 __clear_bit_unlock(bitnum, addr); 79 #endif 80 preempt_enable(); 81 __release(bitlock); 82 } 83 84 /* 85 * Return true if the lock is held. 86 */ 87 static inline int bit_spin_is_locked(int bitnum, unsigned long *addr) 88 { 89 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) 90 return test_bit(bitnum, addr); 91 #elif defined CONFIG_PREEMPT_COUNT 92 return preempt_count(); 93 #else 94 return 1; 95 #endif 96 } 97 98 #endif /* __LINUX_BIT_SPINLOCK_H */ 99 100