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