Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lockdep: spin_lock_nest_lock()

Expose the new lock protection lock.

This can be used to annotate places where we take multiple locks of the
same class and avoid deadlocks by always taking another (top-level) lock
first.

NOTE: we're still bound to the MAX_LOCK_DEPTH (48) limit.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Peter Zijlstra and committed by
Ingo Molnar
b7d39aff 7531e2f3

+21
+2
include/linux/lockdep.h
··· 410 410 #ifdef CONFIG_DEBUG_LOCK_ALLOC 411 411 # ifdef CONFIG_PROVE_LOCKING 412 412 # define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) 413 + # define spin_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) 413 414 # else 414 415 # define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) 416 + # define spin_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, NULL, i) 415 417 # endif 416 418 # define spin_release(l, n, i) lock_release(l, n, i) 417 419 #else
+6
include/linux/spinlock.h
··· 183 183 184 184 #ifdef CONFIG_DEBUG_LOCK_ALLOC 185 185 # define spin_lock_nested(lock, subclass) _spin_lock_nested(lock, subclass) 186 + # define spin_lock_nest_lock(lock, nest_lock) \ 187 + do { \ 188 + typecheck(struct lockdep_map *, &(nest_lock)->dep_map);\ 189 + _spin_lock_nest_lock(lock, &(nest_lock)->dep_map); \ 190 + } while (0) 186 191 #else 187 192 # define spin_lock_nested(lock, subclass) _spin_lock(lock) 193 + # define spin_lock_nest_lock(lock, nest_lock) _spin_lock(lock) 188 194 #endif 189 195 190 196 #define write_lock(lock) _write_lock(lock)
+2
include/linux/spinlock_api_smp.h
··· 22 22 void __lockfunc _spin_lock(spinlock_t *lock) __acquires(lock); 23 23 void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass) 24 24 __acquires(lock); 25 + void __lockfunc _spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *map) 26 + __acquires(lock); 25 27 void __lockfunc _read_lock(rwlock_t *lock) __acquires(lock); 26 28 void __lockfunc _write_lock(rwlock_t *lock) __acquires(lock); 27 29 void __lockfunc _spin_lock_bh(spinlock_t *lock) __acquires(lock);
+11
kernel/spinlock.c
··· 292 292 } 293 293 294 294 EXPORT_SYMBOL(_spin_lock_nested); 295 + 295 296 unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass) 296 297 { 297 298 unsigned long flags; ··· 314 313 } 315 314 316 315 EXPORT_SYMBOL(_spin_lock_irqsave_nested); 316 + 317 + void __lockfunc _spin_lock_nest_lock(spinlock_t *lock, 318 + struct lockdep_map *nest_lock) 319 + { 320 + preempt_disable(); 321 + spin_acquire_nest(&lock->dep_map, 0, 0, nest_lock, _RET_IP_); 322 + LOCK_CONTENDED(lock, _raw_spin_trylock, _raw_spin_lock); 323 + } 324 + 325 + EXPORT_SYMBOL(_spin_lock_nest_lock); 317 326 318 327 #endif 319 328