Skip to content

Commit 32d9959

Browse files
committed
rcu: Add lockdep_assert_in_rcu_read_lock() and friends
There is no direct RCU counterpart to lockdep_assert_irqs_disabled() and friends. Although it is possible to construct them, it would be more convenient to have the following lockdep assertions: lockdep_assert_in_rcu_read_lock() lockdep_assert_in_rcu_read_lock_bh() lockdep_assert_in_rcu_read_lock_sched() lockdep_assert_in_rcu_reader() This commit therefore creates them. Reported-by: Jens Axboe <[email protected]> Signed-off-by: Paul E. McKenney <[email protected]>
1 parent 1613e60 commit 32d9959

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

include/linux/rcupdate.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,71 @@ static inline void rcu_preempt_sleep_check(void) { }
421421
"Illegal context switch in RCU-sched read-side critical section"); \
422422
} while (0)
423423

424+
// See RCU_LOCKDEP_WARN() for an explanation of the double call to
425+
// debug_lockdep_rcu_enabled().
426+
static inline bool lockdep_assert_rcu_helper(bool c)
427+
{
428+
return debug_lockdep_rcu_enabled() &&
429+
(c || !rcu_is_watching() || !rcu_lockdep_current_cpu_online()) &&
430+
debug_lockdep_rcu_enabled();
431+
}
432+
433+
/**
434+
* lockdep_assert_in_rcu_read_lock - WARN if not protected by rcu_read_lock()
435+
*
436+
* Splats if lockdep is enabled and there is no rcu_read_lock() in effect.
437+
*/
438+
#define lockdep_assert_in_rcu_read_lock() \
439+
WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_lock_map)))
440+
441+
/**
442+
* lockdep_assert_in_rcu_read_lock_bh - WARN if not protected by rcu_read_lock_bh()
443+
*
444+
* Splats if lockdep is enabled and there is no rcu_read_lock_bh() in effect.
445+
* Note that local_bh_disable() and friends do not suffice here, instead an
446+
* actual rcu_read_lock_bh() is required.
447+
*/
448+
#define lockdep_assert_in_rcu_read_lock_bh() \
449+
WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_bh_lock_map)))
450+
451+
/**
452+
* lockdep_assert_in_rcu_read_lock_sched - WARN if not protected by rcu_read_lock_sched()
453+
*
454+
* Splats if lockdep is enabled and there is no rcu_read_lock_sched()
455+
* in effect. Note that preempt_disable() and friends do not suffice here,
456+
* instead an actual rcu_read_lock_sched() is required.
457+
*/
458+
#define lockdep_assert_in_rcu_read_lock_sched() \
459+
WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_sched_lock_map)))
460+
461+
/**
462+
* lockdep_assert_in_rcu_reader - WARN if not within some type of RCU reader
463+
*
464+
* Splats if lockdep is enabled and there is no RCU reader of any
465+
* type in effect. Note that regions of code protected by things like
466+
* preempt_disable, local_bh_disable(), and local_irq_disable() all qualify
467+
* as RCU readers.
468+
*
469+
* Note that this will never trigger in PREEMPT_NONE or PREEMPT_VOLUNTARY
470+
* kernels that are not also built with PREEMPT_COUNT. But if you have
471+
* lockdep enabled, you might as well also enable PREEMPT_COUNT.
472+
*/
473+
#define lockdep_assert_in_rcu_reader() \
474+
WARN_ON_ONCE(lockdep_assert_rcu_helper(!lock_is_held(&rcu_lock_map) && \
475+
!lock_is_held(&rcu_bh_lock_map) && \
476+
!lock_is_held(&rcu_sched_lock_map) && \
477+
preemptible()))
478+
424479
#else /* #ifdef CONFIG_PROVE_RCU */
425480

426481
#define RCU_LOCKDEP_WARN(c, s) do { } while (0 && (c))
427482
#define rcu_sleep_check() do { } while (0)
428483

484+
#define lockdep_assert_in_rcu_read_lock() do { } while (0)
485+
#define lockdep_assert_in_rcu_read_lock_bh() do { } while (0)
486+
#define lockdep_assert_in_rcu_read_lock_sched() do { } while (0)
487+
#define lockdep_assert_in_rcu_reader() do { } while (0)
488+
429489
#endif /* #else #ifdef CONFIG_PROVE_RCU */
430490

431491
/*

0 commit comments

Comments
 (0)