1 #ifndef __LINUX_RWLOCK_API_SMP_H 2 #define __LINUX_RWLOCK_API_SMP_H 3 4 #ifndef __LINUX_SPINLOCK_API_SMP_H 5 # error "please don't include this file directly" 6 #endif 7 8 /* 9 * include/linux/rwlock_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 void __lockfunc _read_lock(rwlock_t *lock) __acquires(lock); 19 void __lockfunc _write_lock(rwlock_t *lock) __acquires(lock); 20 void __lockfunc _read_lock_bh(rwlock_t *lock) __acquires(lock); 21 void __lockfunc _write_lock_bh(rwlock_t *lock) __acquires(lock); 22 void __lockfunc _read_lock_irq(rwlock_t *lock) __acquires(lock); 23 void __lockfunc _write_lock_irq(rwlock_t *lock) __acquires(lock); 24 unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) 25 __acquires(lock); 26 unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) 27 __acquires(lock); 28 int __lockfunc _read_trylock(rwlock_t *lock); 29 int __lockfunc _write_trylock(rwlock_t *lock); 30 void __lockfunc _read_unlock(rwlock_t *lock) __releases(lock); 31 void __lockfunc _write_unlock(rwlock_t *lock) __releases(lock); 32 void __lockfunc _read_unlock_bh(rwlock_t *lock) __releases(lock); 33 void __lockfunc _write_unlock_bh(rwlock_t *lock) __releases(lock); 34 void __lockfunc _read_unlock_irq(rwlock_t *lock) __releases(lock); 35 void __lockfunc _write_unlock_irq(rwlock_t *lock) __releases(lock); 36 void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) 37 __releases(lock); 38 void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) 39 __releases(lock); 40 41 #ifdef CONFIG_INLINE_READ_LOCK 42 #define _read_lock(lock) __read_lock(lock) 43 #endif 44 45 #ifdef CONFIG_INLINE_WRITE_LOCK 46 #define _write_lock(lock) __write_lock(lock) 47 #endif 48 49 #ifdef CONFIG_INLINE_READ_LOCK_BH 50 #define _read_lock_bh(lock) __read_lock_bh(lock) 51 #endif 52 53 #ifdef CONFIG_INLINE_WRITE_LOCK_BH 54 #define _write_lock_bh(lock) __write_lock_bh(lock) 55 #endif 56 57 #ifdef CONFIG_INLINE_READ_LOCK_IRQ 58 #define _read_lock_irq(lock) __read_lock_irq(lock) 59 #endif 60 61 #ifdef CONFIG_INLINE_WRITE_LOCK_IRQ 62 #define _write_lock_irq(lock) __write_lock_irq(lock) 63 #endif 64 65 #ifdef CONFIG_INLINE_READ_LOCK_IRQSAVE 66 #define _read_lock_irqsave(lock) __read_lock_irqsave(lock) 67 #endif 68 69 #ifdef CONFIG_INLINE_WRITE_LOCK_IRQSAVE 70 #define _write_lock_irqsave(lock) __write_lock_irqsave(lock) 71 #endif 72 73 #ifdef CONFIG_INLINE_READ_TRYLOCK 74 #define _read_trylock(lock) __read_trylock(lock) 75 #endif 76 77 #ifdef CONFIG_INLINE_WRITE_TRYLOCK 78 #define _write_trylock(lock) __write_trylock(lock) 79 #endif 80 81 #ifdef CONFIG_INLINE_READ_UNLOCK 82 #define _read_unlock(lock) __read_unlock(lock) 83 #endif 84 85 #ifdef CONFIG_INLINE_WRITE_UNLOCK 86 #define _write_unlock(lock) __write_unlock(lock) 87 #endif 88 89 #ifdef CONFIG_INLINE_READ_UNLOCK_BH 90 #define _read_unlock_bh(lock) __read_unlock_bh(lock) 91 #endif 92 93 #ifdef CONFIG_INLINE_WRITE_UNLOCK_BH 94 #define _write_unlock_bh(lock) __write_unlock_bh(lock) 95 #endif 96 97 #ifdef CONFIG_INLINE_READ_UNLOCK_IRQ 98 #define _read_unlock_irq(lock) __read_unlock_irq(lock) 99 #endif 100 101 #ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQ 102 #define _write_unlock_irq(lock) __write_unlock_irq(lock) 103 #endif 104 105 #ifdef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE 106 #define _read_unlock_irqrestore(lock, flags) __read_unlock_irqrestore(lock, flags) 107 #endif 108 109 #ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE 110 #define _write_unlock_irqrestore(lock, flags) __write_unlock_irqrestore(lock, flags) 111 #endif 112 113 static inline int __read_trylock(rwlock_t *lock) 114 { 115 preempt_disable(); 116 if (_raw_read_trylock(lock)) { 117 rwlock_acquire_read(&lock->dep_map, 0, 1, _RET_IP_); 118 return 1; 119 } 120 preempt_enable(); 121 return 0; 122 } 123 124 static inline int __write_trylock(rwlock_t *lock) 125 { 126 preempt_disable(); 127 if (_raw_write_trylock(lock)) { 128 rwlock_acquire(&lock->dep_map, 0, 1, _RET_IP_); 129 return 1; 130 } 131 preempt_enable(); 132 return 0; 133 } 134 135 /* 136 * If lockdep is enabled then we use the non-preemption spin-ops 137 * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are 138 * not re-enabled during lock-acquire (which the preempt-spin-ops do): 139 */ 140 #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) 141 142 static inline void __read_lock(rwlock_t *lock) 143 { 144 preempt_disable(); 145 rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); 146 LOCK_CONTENDED(lock, _raw_read_trylock, _raw_read_lock); 147 } 148 149 static inline unsigned long __read_lock_irqsave(rwlock_t *lock) 150 { 151 unsigned long flags; 152 153 local_irq_save(flags); 154 preempt_disable(); 155 rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); 156 LOCK_CONTENDED_FLAGS(lock, _raw_read_trylock, _raw_read_lock, 157 _raw_read_lock_flags, &flags); 158 return flags; 159 } 160 161 static inline void __read_lock_irq(rwlock_t *lock) 162 { 163 local_irq_disable(); 164 preempt_disable(); 165 rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); 166 LOCK_CONTENDED(lock, _raw_read_trylock, _raw_read_lock); 167 } 168 169 static inline void __read_lock_bh(rwlock_t *lock) 170 { 171 local_bh_disable(); 172 preempt_disable(); 173 rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); 174 LOCK_CONTENDED(lock, _raw_read_trylock, _raw_read_lock); 175 } 176 177 static inline unsigned long __write_lock_irqsave(rwlock_t *lock) 178 { 179 unsigned long flags; 180 181 local_irq_save(flags); 182 preempt_disable(); 183 rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); 184 LOCK_CONTENDED_FLAGS(lock, _raw_write_trylock, _raw_write_lock, 185 _raw_write_lock_flags, &flags); 186 return flags; 187 } 188 189 static inline void __write_lock_irq(rwlock_t *lock) 190 { 191 local_irq_disable(); 192 preempt_disable(); 193 rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); 194 LOCK_CONTENDED(lock, _raw_write_trylock, _raw_write_lock); 195 } 196 197 static inline void __write_lock_bh(rwlock_t *lock) 198 { 199 local_bh_disable(); 200 preempt_disable(); 201 rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); 202 LOCK_CONTENDED(lock, _raw_write_trylock, _raw_write_lock); 203 } 204 205 static inline void __write_lock(rwlock_t *lock) 206 { 207 preempt_disable(); 208 rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); 209 LOCK_CONTENDED(lock, _raw_write_trylock, _raw_write_lock); 210 } 211 212 #endif /* CONFIG_PREEMPT */ 213 214 static inline void __write_unlock(rwlock_t *lock) 215 { 216 rwlock_release(&lock->dep_map, 1, _RET_IP_); 217 _raw_write_unlock(lock); 218 preempt_enable(); 219 } 220 221 static inline void __read_unlock(rwlock_t *lock) 222 { 223 rwlock_release(&lock->dep_map, 1, _RET_IP_); 224 _raw_read_unlock(lock); 225 preempt_enable(); 226 } 227 228 static inline void __read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) 229 { 230 rwlock_release(&lock->dep_map, 1, _RET_IP_); 231 _raw_read_unlock(lock); 232 local_irq_restore(flags); 233 preempt_enable(); 234 } 235 236 static inline void __read_unlock_irq(rwlock_t *lock) 237 { 238 rwlock_release(&lock->dep_map, 1, _RET_IP_); 239 _raw_read_unlock(lock); 240 local_irq_enable(); 241 preempt_enable(); 242 } 243 244 static inline void __read_unlock_bh(rwlock_t *lock) 245 { 246 rwlock_release(&lock->dep_map, 1, _RET_IP_); 247 _raw_read_unlock(lock); 248 preempt_enable_no_resched(); 249 local_bh_enable_ip((unsigned long)__builtin_return_address(0)); 250 } 251 252 static inline void __write_unlock_irqrestore(rwlock_t *lock, 253 unsigned long flags) 254 { 255 rwlock_release(&lock->dep_map, 1, _RET_IP_); 256 _raw_write_unlock(lock); 257 local_irq_restore(flags); 258 preempt_enable(); 259 } 260 261 static inline void __write_unlock_irq(rwlock_t *lock) 262 { 263 rwlock_release(&lock->dep_map, 1, _RET_IP_); 264 _raw_write_unlock(lock); 265 local_irq_enable(); 266 preempt_enable(); 267 } 268 269 static inline void __write_unlock_bh(rwlock_t *lock) 270 { 271 rwlock_release(&lock->dep_map, 1, _RET_IP_); 272 _raw_write_unlock(lock); 273 preempt_enable_no_resched(); 274 local_bh_enable_ip((unsigned long)__builtin_return_address(0)); 275 } 276 277 #endif /* __LINUX_RWLOCK_API_SMP_H */ 278