Changeset 2b4a9f26 in mainline for kernel/generic/include/synch/spinlock.h
- Timestamp:
- 2010-05-20T19:30:18Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 42bbbe2
- Parents:
- b10e6e31
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/synch/spinlock.h
rb10e6e31 r2b4a9f26 49 49 #ifdef CONFIG_DEBUG_SPINLOCK 50 50 const char *name; 51 #endif 51 #endif /* CONFIG_DEBUG_SPINLOCK */ 52 52 } spinlock_t; 53 53 … … 60 60 61 61 /* 62 * SPINLOCK_INITIALIZE is to be used for statically allocated spinlocks. 63 * It declares and initializes the lock. 62 * SPINLOCK_INITIALIZE and SPINLOCK_STATIC_INITIALIZE are to be used 63 * for statically allocated spinlocks. They declare (either as global 64 * or static) symbol and initialize the lock. 64 65 */ 65 66 #ifdef CONFIG_DEBUG_SPINLOCK … … 77 78 } 78 79 79 #define spinlock_lock(lock) spinlock_lock_debug((lock)) 80 #define spinlock_unlock(lock) spinlock_unlock_debug((lock)) 81 82 #else 80 #define ASSERT_SPINLOCK(expr, lock) \ 81 ASSERT_VERBOSE(expr, (lock)->name) 82 83 #define spinlock_lock(lock) spinlock_lock_debug((lock)) 84 #define spinlock_unlock(lock) spinlock_unlock_debug((lock)) 85 86 #else /* CONFIG_DEBUG_SPINLOCK */ 83 87 84 88 #define SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ … … 92 96 } 93 97 94 #define spinlock_lock(lock) atomic_lock_arch(&(lock)->val) 95 #define spinlock_unlock(lock) spinlock_unlock_nondebug((lock)) 96 97 #endif 98 #define ASSERT_SPINLOCK(expr, lock) \ 99 ASSERT(expr) 100 101 #define spinlock_lock(lock) atomic_lock_arch(&(lock)->val) 102 #define spinlock_unlock(lock) spinlock_unlock_nondebug((lock)) 103 104 #endif /* CONFIG_DEBUG_SPINLOCK */ 98 105 99 106 #define SPINLOCK_INITIALIZE(lock_name) \ … … 103 110 SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name) 104 111 105 extern void spinlock_initialize(spinlock_t * lock, const char *name);106 extern int spinlock_trylock(spinlock_t * lock);107 extern void spinlock_lock_debug(spinlock_t * lock);108 extern void spinlock_unlock_debug(spinlock_t * lock);112 extern void spinlock_initialize(spinlock_t *, const char *); 113 extern int spinlock_trylock(spinlock_t *); 114 extern void spinlock_lock_debug(spinlock_t *); 115 extern void spinlock_unlock_debug(spinlock_t *); 109 116 110 117 /** Unlock spinlock … … 113 120 * 114 121 * @param sl Pointer to spinlock_t structure. 122 * 115 123 */ 116 124 static inline void spinlock_unlock_nondebug(spinlock_t *lock) … … 141 149 } 142 150 143 #else 151 #else /* CONFIG_DEBUG_SPINLOCK */ 144 152 145 153 #define DEADLOCK_PROBE_INIT(pname) 146 154 #define DEADLOCK_PROBE(pname, value) 147 155 148 #endif 156 #endif /* CONFIG_DEBUG_SPINLOCK */ 149 157 150 158 #else /* CONFIG_SMP */ … … 160 168 #define SPINLOCK_INITIALIZE_NAME(name, desc_name) 161 169 #define SPINLOCK_STATIC_INITIALIZE_NAME(name, desc_name) 170 171 #define ASSERT_SPINLOCK(expr, lock) 162 172 163 173 #define spinlock_initialize(lock, name) … … 170 180 #define DEADLOCK_PROBE(pname, value) 171 181 182 #endif /* CONFIG_SMP */ 183 184 typedef struct { 185 spinlock_t lock; /**< Spinlock */ 186 bool guard; /**< Flag whether ipl is valid */ 187 ipl_t ipl; /**< Original interrupt level */ 188 } irq_spinlock_t; 189 190 #define IRQ_SPINLOCK_DECLARE(lock_name) irq_spinlock_t lock_name 191 #define IRQ_SPINLOCK_EXTERN(lock_name) extern irq_spinlock_t lock_name 192 193 #define ASSERT_IRQ_SPINLOCK(expr, irq_lock) \ 194 ASSERT_SPINLOCK(expr, &((irq_lock)->lock)) 195 196 /* 197 * IRQ_SPINLOCK_INITIALIZE and IRQ_SPINLOCK_STATIC_INITIALIZE are to be used 198 * for statically allocated interrupts-disabled spinlocks. They declare (either 199 * as global or static symbol) and initialize the lock. 200 */ 201 #ifdef CONFIG_DEBUG_SPINLOCK 202 203 #define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ 204 irq_spinlock_t lock_name = { \ 205 .lock = { \ 206 .name = desc_name, \ 207 .val = { 0 } \ 208 }, \ 209 .guard = false, \ 210 .ipl = 0 \ 211 } 212 213 #define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \ 214 static irq_spinlock_t lock_name = { \ 215 .lock = { \ 216 .name = desc_name, \ 217 .val = { 0 } \ 218 }, \ 219 .guard = false, \ 220 .ipl = 0 \ 221 } 222 223 #else /* CONFIG_DEBUG_SPINLOCK */ 224 225 #define IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, desc_name) \ 226 irq_spinlock_t lock_name = { \ 227 .lock = { \ 228 .val = { 0 } \ 229 }, \ 230 .guard = false, \ 231 .ipl = 0 \ 232 } 233 234 #define IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, desc_name) \ 235 static irq_spinlock_t lock_name = { \ 236 .lock = { \ 237 .val = { 0 } \ 238 }, \ 239 .guard = false, \ 240 .ipl = 0 \ 241 } 242 243 #endif /* CONFIG_DEBUG_SPINLOCK */ 244 245 #define IRQ_SPINLOCK_INITIALIZE(lock_name) \ 246 IRQ_SPINLOCK_INITIALIZE_NAME(lock_name, #lock_name) 247 248 #define IRQ_SPINLOCK_STATIC_INITIALIZE(lock_name) \ 249 IRQ_SPINLOCK_STATIC_INITIALIZE_NAME(lock_name, #lock_name) 250 251 /** Initialize interrupts-disabled spinlock 252 * 253 * @param lock IRQ spinlock to be initialized. 254 * @param name IRQ spinlock name. 255 * 256 */ 257 static inline void irq_spinlock_initialize(irq_spinlock_t *lock, const char *name) 258 { 259 spinlock_initialize(&(lock->lock), name); 260 lock->guard = false; 261 lock->ipl = 0; 262 } 263 264 /** Lock interrupts-disabled spinlock 265 * 266 * Lock a spinlock which requires disabled interrupts. 267 * 268 * @param lock IRQ spinlock to be locked. 269 * @param irq_dis If true, interrupts are actually disabled 270 * prior locking the spinlock. If false, interrupts 271 * are expected to be already disabled. 272 * 273 */ 274 static inline void irq_spinlock_lock(irq_spinlock_t *lock, bool irq_dis) 275 { 276 if (irq_dis) { 277 ipl_t ipl = interrupts_disable(); 278 spinlock_lock(&(lock->lock)); 279 280 lock->guard = true; 281 lock->ipl = ipl; 282 } else { 283 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 284 285 spinlock_lock(&(lock->lock)); 286 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 287 } 288 } 289 290 /** Unlock interrupts-disabled spinlock 291 * 292 * Unlock a spinlock which requires disabled interrupts. 293 * 294 * @param lock IRQ spinlock to be unlocked. 295 * @param irq_res If true, interrupts are restored to previously 296 * saved interrupt level. 297 * 298 */ 299 static inline void irq_spinlock_unlock(irq_spinlock_t *lock, bool irq_res) 300 { 301 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 302 303 if (irq_res) { 304 ASSERT_IRQ_SPINLOCK(lock->guard, lock); 305 306 lock->guard = false; 307 ipl_t ipl = lock->ipl; 308 309 spinlock_unlock(&(lock->lock)); 310 interrupts_restore(ipl); 311 } else { 312 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 313 spinlock_unlock(&(lock->lock)); 314 } 315 } 316 317 /** Lock interrupts-disabled spinlock 318 * 319 * Lock an interrupts-disabled spinlock conditionally. If the 320 * spinlock is not available at the moment, signal failure. 321 * Interrupts are expected to be already disabled. 322 * 323 * @param lock IRQ spinlock to be locked conditionally. 324 * 325 * @return Zero on failure, non-zero otherwise. 326 * 327 */ 328 static inline int irq_spinlock_trylock(irq_spinlock_t *lock) 329 { 330 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), lock); 331 int rc = spinlock_trylock(&(lock->lock)); 332 333 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 334 return rc; 335 } 336 337 /** Pass lock from one interrupts-disabled spinlock to another 338 * 339 * Pass lock from one IRQ spinlock to another IRQ spinlock 340 * without enabling interrupts during the process. 341 * 342 * The first IRQ spinlock is supposed to be locked. 343 * 344 * @param unlock IRQ spinlock to be unlocked. 345 * @param lock IRQ spinlock to be locked. 346 * 347 */ 348 static inline void irq_spinlock_pass(irq_spinlock_t *unlock, 349 irq_spinlock_t *lock) 350 { 351 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 352 353 /* Pass guard from unlock to lock */ 354 bool guard = unlock->guard; 355 ipl_t ipl = unlock->ipl; 356 unlock->guard = false; 357 358 spinlock_unlock(&(unlock->lock)); 359 spinlock_lock(&(lock->lock)); 360 361 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 362 363 if (guard) { 364 lock->guard = true; 365 lock->ipl = ipl; 366 } 367 } 368 369 /** Hand-over-hand locking of interrupts-disabled spinlocks 370 * 371 * Implement hand-over-hand locking between two interrupts-disabled 372 * spinlocks without enabling interrupts during the process. 373 * 374 * The first IRQ spinlock is supposed to be locked. 375 * 376 * @param unlock IRQ spinlock to be unlocked. 377 * @param lock IRQ spinlock to be locked. 378 * 379 */ 380 static inline void irq_spinlock_exchange(irq_spinlock_t *unlock, 381 irq_spinlock_t *lock) 382 { 383 ASSERT_IRQ_SPINLOCK(interrupts_disabled(), unlock); 384 385 spinlock_lock(&(lock->lock)); 386 ASSERT_IRQ_SPINLOCK(!lock->guard, lock); 387 388 /* Pass guard from unlock to lock */ 389 if (unlock->guard) { 390 lock->guard = true; 391 lock->ipl = unlock->ipl; 392 unlock->guard = false; 393 } 394 395 spinlock_unlock(&(unlock->lock)); 396 } 397 172 398 #endif 173 399 174 #endif175 176 400 /** @} 177 401 */
Note:
See TracChangeset
for help on using the changeset viewer.