aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2009-11-13 22:51:39 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-14 04:31:42 -0500
commit2f51f9884f6a36b0fe9636d5a1937e5cbd25723b (patch)
tree0505e111a9714b2bd022322f76e6c4de26861107 /kernel/rcutree.c
parent560d4bc0df9a5e63b980432282d8c2bd3559ec74 (diff)
rcu: Eliminate __rcu_pending() false positives
Now that there are both ->gpnum and ->completed fields in the rcu_node structure, __rcu_pending() should check rdp->gpnum and rdp->completed against rnp->gpnum and rdp->completed, respectively, instead of the prior comparison against the rcu_state fields rsp->gpnum and rsp->completed. Given the old comparison, __rcu_pending() could return 1, resulting in a needless raise_softirq(RCU_SOFTIRQ). This useless work would happen if RCU responded to a scheduling-clock interrupt after the rcu_state fields had been updated, but before the rcu_node fields had been updated. Changing the comparison from the rcu_state fields to the rcu_node fields prevents this useless work from happening. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: laijs@cn.fujitsu.com Cc: dipankar@in.ibm.com Cc: mathieu.desnoyers@polymtl.ca Cc: josh@joshtriplett.org Cc: dvhltc@us.ibm.com Cc: niv@us.ibm.com Cc: peterz@infradead.org Cc: rostedt@goodmis.org Cc: Valdis.Kletnieks@vt.edu Cc: dhowells@redhat.com LKML-Reference: <12581706991966-git-send-email-> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 24bbf2ce0605..9b36d6d7fb97 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1403,6 +1403,8 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);
1403 */ 1403 */
1404static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp) 1404static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
1405{ 1405{
1406 struct rcu_node *rnp = rdp->mynode;
1407
1406 rdp->n_rcu_pending++; 1408 rdp->n_rcu_pending++;
1407 1409
1408 /* Check for CPU stalls, if enabled. */ 1410 /* Check for CPU stalls, if enabled. */
@@ -1427,13 +1429,13 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
1427 } 1429 }
1428 1430
1429 /* Has another RCU grace period completed? */ 1431 /* Has another RCU grace period completed? */
1430 if (ACCESS_ONCE(rsp->completed) != rdp->completed) { /* outside lock */ 1432 if (ACCESS_ONCE(rnp->completed) != rdp->completed) { /* outside lock */
1431 rdp->n_rp_gp_completed++; 1433 rdp->n_rp_gp_completed++;
1432 return 1; 1434 return 1;
1433 } 1435 }
1434 1436
1435 /* Has a new RCU grace period started? */ 1437 /* Has a new RCU grace period started? */
1436 if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) { /* outside lock */ 1438 if (ACCESS_ONCE(rnp->gpnum) != rdp->gpnum) { /* outside lock */
1437 rdp->n_rp_gp_started++; 1439 rdp->n_rp_gp_started++;
1438 return 1; 1440 return 1;
1439 } 1441 }