aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-06-19 14:58:27 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-07-02 15:34:25 -0400
commit95f0c1de3e6ed4383cc4b5f52ce4ecfb21026b49 (patch)
tree8099a405c03d9caabbf8f1752346e0aa0e30ee28 /kernel/rcutree.c
parent1c17e4d4437d8045a596d9f06c1558dc09e2b372 (diff)
rcu: Disable preemption in rcu_blocking_is_gp()
It is time to optimize CONFIG_TREE_PREEMPT_RCU's synchronize_rcu() for uniprocessor optimization, which means that rcu_blocking_is_gp() can no longer rely on RCU read-side critical sections having disabled preemption. This commit therefore disables preemption across rcu_blocking_is_gp()'s scan of the cpu_online_mask. (Updated from previous version to fix embarrassing bug spotted by Wu Fengguang.) Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c24
1 files changed, 6 insertions, 18 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 70c4da7d2a97..e000a623e635 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1981,28 +1981,16 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);
1981 * occasionally incorrectly indicate that there are multiple CPUs online 1981 * occasionally incorrectly indicate that there are multiple CPUs online
1982 * when there was in fact only one the whole time, as this just adds 1982 * when there was in fact only one the whole time, as this just adds
1983 * some overhead: RCU still operates correctly. 1983 * some overhead: RCU still operates correctly.
1984 *
1985 * Of course, sampling num_online_cpus() with preemption enabled can
1986 * give erroneous results if there are concurrent CPU-hotplug operations.
1987 * For example, given a demonic sequence of preemptions in num_online_cpus()
1988 * and CPU-hotplug operations, there could be two or more CPUs online at
1989 * all times, but num_online_cpus() might well return one (or even zero).
1990 *
1991 * However, all such demonic sequences require at least one CPU-offline
1992 * operation. Furthermore, rcu_blocking_is_gp() giving the wrong answer
1993 * is only a problem if there is an RCU read-side critical section executing
1994 * throughout. But RCU-sched and RCU-bh read-side critical sections
1995 * disable either preemption or bh, which prevents a CPU from going offline.
1996 * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
1997 * that there is only one CPU when in fact there was more than one throughout
1998 * is when there were no RCU readers in the system. If there are no
1999 * RCU readers, the grace period by definition can be of zero length,
2000 * regardless of the number of online CPUs.
2001 */ 1984 */
2002static inline int rcu_blocking_is_gp(void) 1985static inline int rcu_blocking_is_gp(void)
2003{ 1986{
1987 int ret;
1988
2004 might_sleep(); /* Check for RCU read-side critical section. */ 1989 might_sleep(); /* Check for RCU read-side critical section. */
2005 return num_online_cpus() <= 1; 1990 preempt_disable();
1991 ret = num_online_cpus() <= 1;
1992 preempt_enable();
1993 return ret;
2006} 1994}
2007 1995
2008/** 1996/**