diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-07-02 17:42:01 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-09-23 10:42:49 -0400 |
commit | e3ebfb96f396731ca2d0b108785d5da31b53ab00 (patch) | |
tree | 7bac429c3cad5f00894746270322d5a4119cea47 | |
parent | a10d206ef1a83121ab7430cb196e0376a7145b22 (diff) |
rcu: Add PROVE_RCU_DELAY to provoke difficult races
There have been some recent bugs that were triggered only when
preemptible RCU's __rcu_read_unlock() was preempted just after setting
->rcu_read_lock_nesting to INT_MIN, which is a low-probability event.
Therefore, reproducing those bugs (to say nothing of gaining confidence
in alleged fixes) was quite difficult. This commit therefore creates
a new debug-only RCU kernel config option that forces a short delay
in __rcu_read_unlock() to increase the probability of those sorts of
bugs occurring.
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r-- | kernel/rcupdate.c | 4 | ||||
-rw-r--r-- | lib/Kconfig.debug | 14 |
2 files changed, 18 insertions, 0 deletions
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 4e6a61b15e86..29ca1c6da594 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/export.h> | 46 | #include <linux/export.h> |
47 | #include <linux/hardirq.h> | 47 | #include <linux/hardirq.h> |
48 | #include <linux/delay.h> | ||
48 | 49 | ||
49 | #define CREATE_TRACE_POINTS | 50 | #define CREATE_TRACE_POINTS |
50 | #include <trace/events/rcu.h> | 51 | #include <trace/events/rcu.h> |
@@ -81,6 +82,9 @@ void __rcu_read_unlock(void) | |||
81 | } else { | 82 | } else { |
82 | barrier(); /* critical section before exit code. */ | 83 | barrier(); /* critical section before exit code. */ |
83 | t->rcu_read_lock_nesting = INT_MIN; | 84 | t->rcu_read_lock_nesting = INT_MIN; |
85 | #ifdef CONFIG_PROVE_RCU_DELAY | ||
86 | udelay(10); /* Make preemption more probable. */ | ||
87 | #endif /* #ifdef CONFIG_PROVE_RCU_DELAY */ | ||
84 | barrier(); /* assign before ->rcu_read_unlock_special load */ | 88 | barrier(); /* assign before ->rcu_read_unlock_special load */ |
85 | if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special))) | 89 | if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special))) |
86 | rcu_read_unlock_special(t); | 90 | rcu_read_unlock_special(t); |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2403a63b5da5..dacbbe4d7a80 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -629,6 +629,20 @@ config PROVE_RCU_REPEATEDLY | |||
629 | 629 | ||
630 | Say N if you are unsure. | 630 | Say N if you are unsure. |
631 | 631 | ||
632 | config PROVE_RCU_DELAY | ||
633 | bool "RCU debugging: preemptible RCU race provocation" | ||
634 | depends on DEBUG_KERNEL && PREEMPT_RCU | ||
635 | default n | ||
636 | help | ||
637 | There is a class of races that involve an unlikely preemption | ||
638 | of __rcu_read_unlock() just after ->rcu_read_lock_nesting has | ||
639 | been set to INT_MIN. This feature inserts a delay at that | ||
640 | point to increase the probability of these races. | ||
641 | |||
642 | Say Y to increase probability of preemption of __rcu_read_unlock(). | ||
643 | |||
644 | Say N if you are unsure. | ||
645 | |||
632 | config SPARSE_RCU_POINTER | 646 | config SPARSE_RCU_POINTER |
633 | bool "RCU debugging: sparse-based checks for pointer usage" | 647 | bool "RCU debugging: sparse-based checks for pointer usage" |
634 | default n | 648 | default n |