aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/rcutree.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 074cb2d974bf..2015bce749f9 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1396,6 +1396,9 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
1396 rcu_for_each_node_breadth_first(rsp, rnp) { 1396 rcu_for_each_node_breadth_first(rsp, rnp) {
1397 raw_spin_lock_irq(&rnp->lock); 1397 raw_spin_lock_irq(&rnp->lock);
1398 rnp->completed = rsp->gpnum; 1398 rnp->completed = rsp->gpnum;
1399 rdp = this_cpu_ptr(rsp->rda);
1400 if (rnp == rdp->mynode)
1401 __rcu_process_gp_end(rsp, rnp, rdp);
1399 nocb += rcu_nocb_gp_cleanup(rsp, rnp); 1402 nocb += rcu_nocb_gp_cleanup(rsp, rnp);
1400 raw_spin_unlock_irq(&rnp->lock); 1403 raw_spin_unlock_irq(&rnp->lock);
1401 cond_resched(); 1404 cond_resched();
@@ -1408,6 +1411,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
1408 trace_rcu_grace_period(rsp->name, rsp->completed, "end"); 1411 trace_rcu_grace_period(rsp->name, rsp->completed, "end");
1409 rsp->fqs_state = RCU_GP_IDLE; 1412 rsp->fqs_state = RCU_GP_IDLE;
1410 rdp = this_cpu_ptr(rsp->rda); 1413 rdp = this_cpu_ptr(rsp->rda);
1414 rcu_advance_cbs(rsp, rnp, rdp); /* Reduce false positives below. */
1411 if (cpu_needs_another_gp(rsp, rdp)) 1415 if (cpu_needs_another_gp(rsp, rdp))
1412 rsp->gp_flags = 1; 1416 rsp->gp_flags = 1;
1413 raw_spin_unlock_irq(&rnp->lock); 1417 raw_spin_unlock_irq(&rnp->lock);
@@ -1497,6 +1501,15 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
1497 struct rcu_data *rdp = this_cpu_ptr(rsp->rda); 1501 struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
1498 struct rcu_node *rnp = rcu_get_root(rsp); 1502 struct rcu_node *rnp = rcu_get_root(rsp);
1499 1503
1504 /*
1505 * If there is no grace period in progress right now, any
1506 * callbacks we have up to this point will be satisfied by the
1507 * next grace period. Also, advancing the callbacks reduces the
1508 * probability of false positives from cpu_needs_another_gp()
1509 * resulting in pointless grace periods. So, advance callbacks!
1510 */
1511 rcu_advance_cbs(rsp, rnp, rdp);
1512
1500 if (!rsp->gp_kthread || 1513 if (!rsp->gp_kthread ||
1501 !cpu_needs_another_gp(rsp, rdp)) { 1514 !cpu_needs_another_gp(rsp, rdp)) {
1502 /* 1515 /*
@@ -1509,14 +1522,6 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
1509 return; 1522 return;
1510 } 1523 }
1511 1524
1512 /*
1513 * Because there is no grace period in progress right now,
1514 * any callbacks we have up to this point will be satisfied
1515 * by the next grace period. So this is a good place to
1516 * assign a grace period number to recently posted callbacks.
1517 */
1518 rcu_accelerate_cbs(rsp, rnp, rdp);
1519
1520 rsp->gp_flags = RCU_GP_FLAG_INIT; 1525 rsp->gp_flags = RCU_GP_FLAG_INIT;
1521 raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */ 1526 raw_spin_unlock(&rnp->lock); /* Interrupts remain disabled. */
1522 1527