Skip to content

Commit

Permalink
rcu: optionally leave lockdep enabled after RCU lockdep splat
Browse files Browse the repository at this point in the history
There is no need to disable lockdep after an RCU lockdep splat,
so remove the debug_lockdeps_off() from lockdep_rcu_dereference().
To avoid repeated lockdep splats, use a static variable in the inlined
rcu_dereference_check() and rcu_dereference_protected() macros so that
a given instance splats only once, but so that multiple instances can
be detected per boot.

This is controlled by a new config variable CONFIG_PROVE_RCU_REPEATEDLY,
which is disabled by default.  This provides the normal lockdep behavior
by default, but permits people who want to find multiple RCU-lockdep
splats per boot to easily do so.

Requested-by: Eric Paris <[email protected]>
Signed-off-by: Lai Jiangshan <[email protected]>
Tested-by: Eric Paris <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
  • Loading branch information
Lai Jiangshan authored and paulmck committed May 10, 2010
1 parent b57f95a commit 2b3fc35
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 4 deletions.
15 changes: 11 additions & 4 deletions include/linux/rcupdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,15 @@ static inline int rcu_read_lock_sched_held(void)

extern int rcu_my_thread_group_empty(void);

#define __do_rcu_dereference_check(c) \
do { \
static bool __warned; \
if (debug_lockdep_rcu_enabled() && !__warned && !(c)) { \
__warned = true; \
lockdep_rcu_dereference(__FILE__, __LINE__); \
} \
} while (0)

/**
* rcu_dereference_check - rcu_dereference with debug checking
* @p: The pointer to read, prior to dereferencing
Expand Down Expand Up @@ -221,8 +230,7 @@ extern int rcu_my_thread_group_empty(void);
*/
#define rcu_dereference_check(p, c) \
({ \
if (debug_lockdep_rcu_enabled() && !(c)) \
lockdep_rcu_dereference(__FILE__, __LINE__); \
__do_rcu_dereference_check(c); \
rcu_dereference_raw(p); \
})

Expand All @@ -239,8 +247,7 @@ extern int rcu_my_thread_group_empty(void);
*/
#define rcu_dereference_protected(p, c) \
({ \
if (debug_lockdep_rcu_enabled() && !(c)) \
lockdep_rcu_dereference(__FILE__, __LINE__); \
__do_rcu_dereference_check(c); \
(p); \
})

Expand Down
3 changes: 3 additions & 0 deletions kernel/lockdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -3801,8 +3801,11 @@ void lockdep_rcu_dereference(const char *file, const int line)
{
struct task_struct *curr = current;

#ifndef CONFIG_PROVE_RCU_REPEATEDLY
if (!debug_locks_off())
return;
#endif /* #ifdef CONFIG_PROVE_RCU_REPEATEDLY */
/* Note: the following can be executed concurrently, so be careful. */
printk("\n===================================================\n");
printk( "[ INFO: suspicious rcu_dereference_check() usage. ]\n");
printk( "---------------------------------------------------\n");
Expand Down
12 changes: 12 additions & 0 deletions lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,18 @@ config PROVE_RCU

Say N if you are unsure.

config PROVE_RCU_REPEATEDLY
bool "RCU debugging: don't disable PROVE_RCU on first splat"
depends on PROVE_RCU
default n
help
By itself, PROVE_RCU will disable checking upon issuing the
first warning (or "splat"). This feature prevents such
disabling, allowing multiple RCU-lockdep warnings to be printed
on a single reboot.

Say N if you are unsure.

config LOCKDEP
bool
depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
Expand Down

0 comments on commit 2b3fc35

Please sign in to comment.