1 #ifndef __LINUX_SPINLOCK_API_SMP_H 2 #define __LINUX_SPINLOCK_API_SMP_H 3 4 #ifndef __LINUX_SPINLOCK_H 5 # error "please don't include this file directly" 6 #endif 7 8 /* 9 * include/linux/spinlock_api_smp.h 10 * 11 * spinlock API declarations on SMP (and debug) 12 * (implemented in kernel/spinlock.c) 13 * 14 * portions Copyright 2005, Red Hat, Inc., Ingo Molnar 15 * Released under the General Public License (GPL). 16 */ 17 18 int in_lock_functions(unsigned long addr); 19 20 #define assert_raw_spin_locked(x) BUG_ON(!raw_spin_is_locked(x)) 21 22 void __lockfunc _spin_lock(raw_spinlock_t *lock) __acquires(lock); 23 void __lockfunc _spin_lock_nested(raw_spinlock_t *lock, int subclass) 24 __acquires(lock); 25 void __lockfunc 26 _spin_lock_nest_lock(raw_spinlock_t *lock, struct lockdep_map *map) 27 __acquires(lock); 28 void __lockfunc _spin_lock_bh(raw_spinlock_t *lock) __acquires(lock); 29 void __lockfunc _spin_lock_irq(raw_spinlock_t *lock) __acquires(lock); 30 31 unsigned long __lockfunc _spin_lock_irqsave(raw_spinlock_t *lock) 32 __acquires(lock); 33 unsigned long __lockfunc 34 _spin_lock_irqsave_nested(raw_spinlock_t *lock, int subclass) 35 __acquires(lock); 36 int __lockfunc _spin_trylock(raw_spinlock_t *lock); 37 int __lockfunc _spin_trylock_bh(raw_spinlock_t *lock); 38 void __lockfunc _spin_unlock(raw_spinlock_t *lock) __releases(lock); 39 void __lockfunc _spin_unlock_bh(raw_spinlock_t *lock) __releases(lock); 40 void __lockfunc _spin_unlock_irq(raw_spinlock_t *lock) __releases(lock); 41 void __lockfunc 42 _spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) 43 __releases(lock); 44 45 #ifdef CONFIG_INLINE_SPIN_LOCK 46 #define _spin_lock(lock) __spin_lock(lock) 47 #endif 48 49 #ifdef CONFIG_INLINE_SPIN_LOCK_BH 50 #define _spin_lock_bh(lock) __spin_lock_bh(lock) 51 #endif 52 53 #ifdef CONFIG_INLINE_SPIN_LOCK_IRQ 54 #define _spin_lock_irq(lock) __spin_lock_irq(lock) 55 #endif 56 57 #ifdef CONFIG_INLINE_SPIN_LOCK_IRQSAVE 58 #define _spin_lock_irqsave(lock) __spin_lock_irqsave(lock) 59 #endif 60 61 #ifdef CONFIG_INLINE_SPIN_TRYLOCK 62 #define _spin_trylock(lock) __spin_trylock(lock) 63 #endif 64 65 #ifdef CONFIG_INLINE_SPIN_TRYLOCK_BH 66 #define _spin_trylock_bh(lock) __spin_trylock_bh(lock) 67 #endif 68 69 #ifdef CONFIG_INLINE_SPIN_UNLOCK 70 #define _spin_unlock(lock) __spin_unlock(lock) 71 #endif 72 73 #ifdef CONFIG_INLINE_SPIN_UNLOCK_BH 74 #define _spin_unlock_bh(lock) __spin_unlock_bh(lock) 75 #endif 76 77 #ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQ 78 #define _spin_unlock_irq(lock) __spin_unlock_irq(lock) 79 #endif 80 81 #ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE 82 #define _spin_unlock_irqrestore(lock, flags) __spin_unlock_irqrestore(lock, flags) 83 #endif 84 85 static inline int __spin_trylock(raw_spinlock_t *lock) 86 { 87 preempt_disable(); 88 if (do_raw_spin_trylock(lock)) { 89 spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); 90 return 1; 91 } 92 preempt_enable(); 93 return 0; 94 } 95 96 /* 97 * If lockdep is enabled then we use the non-preemption spin-ops 98 * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are 99 * not re-enabled during lock-acquire (which the preempt-spin-ops do): 100 */ 101 #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) 102 103 static inline unsigned long __spin_lock_irqsave(raw_spinlock_t *lock) 104 { 105 unsigned long flags; 106 107 local_irq_save(flags); 108 preempt_disable(); 109 spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); 110 /* 111 * On lockdep we dont want the hand-coded irq-enable of 112 * do_raw_spin_lock_flags() code, because lockdep assumes 113 * that interrupts are not re-enabled during lock-acquire: 114 */ 115 #ifdef CONFIG_LOCKDEP 116 LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); 117 #else 118 do_raw_spin_lock_flags(lock, &flags); 119 #endif 120 return flags; 121 } 122 123 static inline void __spin_lock_irq(raw_spinlock_t *lock) 124 { 125 local_irq_disable(); 126 preempt_disable(); 127 spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); 128 LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); 129 } 130 131 static inline void __spin_lock_bh(raw_spinlock_t *lock) 132 { 133 local_bh_disable(); 134 preempt_disable(); 135 spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); 136 LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); 137 } 138 139 static inline void __spin_lock(raw_spinlock_t *lock) 140 { 141 preempt_disable(); 142 spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); 143 LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); 144 } 145 146 #endif /* CONFIG_PREEMPT */ 147 148 static inline void __spin_unlock(raw_spinlock_t *lock) 149 { 150 spin_release(&lock->dep_map, 1, _RET_IP_); 151 do_raw_spin_unlock(lock); 152 preempt_enable(); 153 } 154 155 static inline void __spin_unlock_irqrestore(raw_spinlock_t *lock, 156 unsigned long flags) 157 { 158 spin_release(&lock->dep_map, 1, _RET_IP_); 159 do_raw_spin_unlock(lock); 160 local_irq_restore(flags); 161 preempt_enable(); 162 } 163 164 static inline void __spin_unlock_irq(raw_spinlock_t *lock) 165 { 166 spin_release(&lock->dep_map, 1, _RET_IP_); 167 do_raw_spin_unlock(lock); 168 local_irq_enable(); 169 preempt_enable(); 170 } 171 172 static inline void __spin_unlock_bh(raw_spinlock_t *lock) 173 { 174 spin_release(&lock->dep_map, 1, _RET_IP_); 175 do_raw_spin_unlock(lock); 176 preempt_enable_no_resched(); 177 local_bh_enable_ip((unsigned long)__builtin_return_address(0)); 178 } 179 180 static inline int __spin_trylock_bh(raw_spinlock_t *lock) 181 { 182 local_bh_disable(); 183 preempt_disable(); 184 if (do_raw_spin_trylock(lock)) { 185 spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); 186 return 1; 187 } 188 preempt_enable_no_resched(); 189 local_bh_enable_ip((unsigned long)__builtin_return_address(0)); 190 return 0; 191 } 192 193 #include <linux/rwlock_api_smp.h> 194 195 #endif /* __LINUX_SPINLOCK_API_SMP_H */ 196