aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2010-12-10 16:11:11 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-12-17 15:34:19 -0500
commit5ff8e6f0535fe730e921ca347bc38dcb9e01791a (patch)
tree84940db74c49e9312cd6b0295fa03a04603673a3 /kernel/rcutree.c
parent20377f32dcb77941d450728da18cce5b1a7faec5 (diff)
rcu: Keep gpnum and completed fields synchronized
When a CPU that was in an extended quiescent state wakes up and catches up with grace periods that remote CPUs completed on its behalf, we update the completed field but not the gpnum that keeps a stale value of a backward grace period ID. Later, note_new_gpnum() will interpret the shift between the local CPU and the node grace period ID as some new grace period to handle and will then start to hunt quiescent state. But if every grace periods have already been completed, this interpretation becomes broken. And we'll be stuck in clusters of spurious softirqs because rcu_report_qs_rdp() will make this broken state run into infinite loop. The solution, as suggested by Lai Jiangshan, is to ensure that the gpnum and completed fields are well synchronized when we catch up with completed grace periods on their behalf by other cpus. This way we won't start noting spurious new grace periods. Suggested-by: Lai Jiangshan <laijs@cn.fujitsu.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Steven Rostedt <rostedt@goodmis.org Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 916f42b39f1e..8105271fc10e 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -680,6 +680,15 @@ __rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat
680 rdp->completed = rnp->completed; 680 rdp->completed = rnp->completed;
681 681
682 /* 682 /*
683 * If we were in an extended quiescent state, we may have
684 * missed some grace periods that others CPUs took care on
685 * our behalf. Catch up with this state to avoid noting
686 * spurious new grace periods.
687 */
688 if (rdp->completed > rdp->gpnum)
689 rdp->gpnum = rdp->completed;
690
691 /*
683 * If another CPU handled our extended quiescent states and 692 * If another CPU handled our extended quiescent states and
684 * we have no more grace period to complete yet, then stop 693 * we have no more grace period to complete yet, then stop
685 * chasing quiescent states. 694 * chasing quiescent states.