Commit 1b963c81b14509e330e0fe3218b645ece2738dc5

Authored by Jiri Kosina
Committed by Linus Torvalds
1 parent fef6c12e88

lockdep, rwsem: provide down_write_nest_lock()

down_write_nest_lock() provides a means to annotate locking scenario
where an outer lock is guaranteed to serialize the order nested locks
are being acquired.

This is analogoue to already existing mutex_lock_nest_lock() and
spin_lock_nest_lock().

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Cc: Rik van Riel <riel@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mel Gorman <mel@csn.ul.ie>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 22 additions and 0 deletions Side-by-side Diff

include/linux/lockdep.h
... ... @@ -524,14 +524,17 @@
524 524 #ifdef CONFIG_DEBUG_LOCK_ALLOC
525 525 # ifdef CONFIG_PROVE_LOCKING
526 526 # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i)
  527 +# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i)
527 528 # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, NULL, i)
528 529 # else
529 530 # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i)
  531 +# define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i)
530 532 # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, NULL, i)
531 533 # endif
532 534 # define rwsem_release(l, n, i) lock_release(l, n, i)
533 535 #else
534 536 # define rwsem_acquire(l, s, t, i) do { } while (0)
  537 +# define rwsem_acquire_nest(l, s, t, n, i) do { } while (0)
535 538 # define rwsem_acquire_read(l, s, t, i) do { } while (0)
536 539 # define rwsem_release(l, n, i) do { } while (0)
537 540 #endif
include/linux/rwsem.h
... ... @@ -125,8 +125,17 @@
125 125 */
126 126 extern void down_read_nested(struct rw_semaphore *sem, int subclass);
127 127 extern void down_write_nested(struct rw_semaphore *sem, int subclass);
  128 +extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
  129 +
  130 +# define down_write_nest_lock(sem, nest_lock) \
  131 +do { \
  132 + typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \
  133 + _down_write_nest_lock(sem, &(nest_lock)->dep_map); \
  134 +} while (0);
  135 +
128 136 #else
129 137 # define down_read_nested(sem, subclass) down_read(sem)
  138 +# define down_write_nest_lock(sem, nest_lock) down_read(sem)
130 139 # define down_write_nested(sem, subclass) down_write(sem)
131 140 #endif
132 141  
... ... @@ -116,6 +116,16 @@
116 116  
117 117 EXPORT_SYMBOL(down_read_nested);
118 118  
  119 +void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
  120 +{
  121 + might_sleep();
  122 + rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
  123 +
  124 + LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
  125 +}
  126 +
  127 +EXPORT_SYMBOL(_down_write_nest_lock);
  128 +
119 129 void down_write_nested(struct rw_semaphore *sem, int subclass)
120 130 {
121 131 might_sleep();