aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-12-31 05:24:21 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2013-03-26 11:04:58 -0400
commit910ee45db2f4837c8440e770474758493ab94bf7 (patch)
treedbc53615c3874cf1ea5588677e7b5f48462dcaff /kernel/rcutree.c
parent0446be489795d8bb994125a916ef03211f539e54 (diff)
rcu: Make rcu_accelerate_cbs() note need for future grace periods
Now that rcu_start_future_gp() has been abstracted from rcu_nocb_wait_gp(), rcu_accelerate_cbs() can invoke rcu_start_future_gp() so as to register the need for any future grace periods needed by a CPU about to enter dyntick-idle mode. This commit makes this change. Note that some refactoring of rcu_start_gp() is carried out to avoid recursion and subsequent self-deadlocks. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index f4b23f16677a..9cb91e4885af 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -224,7 +224,8 @@ static ulong jiffies_till_next_fqs = RCU_JIFFIES_TILL_FORCE_QS;
224module_param(jiffies_till_first_fqs, ulong, 0644); 224module_param(jiffies_till_first_fqs, ulong, 0644);
225module_param(jiffies_till_next_fqs, ulong, 0644); 225module_param(jiffies_till_next_fqs, ulong, 0644);
226 226
227static void rcu_start_gp(struct rcu_state *rsp); 227static void rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
228 struct rcu_data *rdp);
228static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)); 229static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *));
229static void force_quiescent_state(struct rcu_state *rsp); 230static void force_quiescent_state(struct rcu_state *rsp);
230static int rcu_pending(int cpu); 231static int rcu_pending(int cpu);
@@ -1162,7 +1163,7 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp)
1162 trace_rcu_future_gp(rnp, rdp, c, "Startedleafroot"); 1163 trace_rcu_future_gp(rnp, rdp, c, "Startedleafroot");
1163 } else { 1164 } else {
1164 trace_rcu_future_gp(rnp, rdp, c, "Startedroot"); 1165 trace_rcu_future_gp(rnp, rdp, c, "Startedroot");
1165 rcu_start_gp(rdp->rsp); 1166 rcu_start_gp_advanced(rdp->rsp, rnp_root, rdp);
1166 } 1167 }
1167unlock_out: 1168unlock_out:
1168 if (rnp != rnp_root) 1169 if (rnp != rnp_root)
@@ -1248,6 +1249,8 @@ static void rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
1248 rdp->nxttail[i] = rdp->nxttail[RCU_NEXT_TAIL]; 1249 rdp->nxttail[i] = rdp->nxttail[RCU_NEXT_TAIL];
1249 rdp->nxtcompleted[i] = c; 1250 rdp->nxtcompleted[i] = c;
1250 } 1251 }
1252 /* Record any needed additional grace periods. */
1253 rcu_start_future_gp(rnp, rdp);
1251 1254
1252 /* Trace depending on how much we were able to accelerate. */ 1255 /* Trace depending on how much we were able to accelerate. */
1253 if (!*rdp->nxttail[RCU_WAIT_TAIL]) 1256 if (!*rdp->nxttail[RCU_WAIT_TAIL])
@@ -1609,20 +1612,9 @@ static int __noreturn rcu_gp_kthread(void *arg)
1609 * quiescent state. 1612 * quiescent state.
1610 */ 1613 */
1611static void 1614static void
1612rcu_start_gp(struct rcu_state *rsp) 1615rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp,
1616 struct rcu_data *rdp)
1613{ 1617{
1614 struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
1615 struct rcu_node *rnp = rcu_get_root(rsp);
1616
1617 /*
1618 * If there is no grace period in progress right now, any
1619 * callbacks we have up to this point will be satisfied by the
1620 * next grace period. Also, advancing the callbacks reduces the
1621 * probability of false positives from cpu_needs_another_gp()
1622 * resulting in pointless grace periods. So, advance callbacks!
1623 */
1624 rcu_advance_cbs(rsp, rnp, rdp);
1625
1626 if (!rsp->gp_kthread || !cpu_needs_another_gp(rsp, rdp)) { 1618 if (!rsp->gp_kthread || !cpu_needs_another_gp(rsp, rdp)) {
1627 /* 1619 /*
1628 * Either we have not yet spawned the grace-period 1620 * Either we have not yet spawned the grace-period
@@ -1634,14 +1626,36 @@ rcu_start_gp(struct rcu_state *rsp)
1634 } 1626 }
1635 rsp->gp_flags = RCU_GP_FLAG_INIT; 1627 rsp->gp_flags = RCU_GP_FLAG_INIT;
1636 1628
1637 /* Ensure that CPU is aware of completion of last grace period. */
1638 __rcu_process_gp_end(rsp, rdp->mynode, rdp);
1639
1640 /* Wake up rcu_gp_kthread() to start the grace period. */ 1629 /* Wake up rcu_gp_kthread() to start the grace period. */
1641 wake_up(&rsp->gp_wq); 1630 wake_up(&rsp->gp_wq);
1642} 1631}
1643 1632
1644/* 1633/*
1634 * Similar to rcu_start_gp_advanced(), but also advance the calling CPU's
1635 * callbacks. Note that rcu_start_gp_advanced() cannot do this because it
1636 * is invoked indirectly from rcu_advance_cbs(), which would result in
1637 * endless recursion -- or would do so if it wasn't for the self-deadlock
1638 * that is encountered beforehand.
1639 */
1640static void
1641rcu_start_gp(struct rcu_state *rsp)
1642{
1643 struct rcu_data *rdp = this_cpu_ptr(rsp->rda);
1644 struct rcu_node *rnp = rcu_get_root(rsp);
1645
1646 /*
1647 * If there is no grace period in progress right now, any
1648 * callbacks we have up to this point will be satisfied by the
1649 * next grace period. Also, advancing the callbacks reduces the
1650 * probability of false positives from cpu_needs_another_gp()
1651 * resulting in pointless grace periods. So, advance callbacks
1652 * then start the grace period!
1653 */
1654 rcu_advance_cbs(rsp, rnp, rdp);
1655 rcu_start_gp_advanced(rsp, rnp, rdp);
1656}
1657
1658/*
1645 * Report a full set of quiescent states to the specified rcu_state 1659 * Report a full set of quiescent states to the specified rcu_state
1646 * data structure. This involves cleaning up after the prior grace 1660 * data structure. This involves cleaning up after the prior grace
1647 * period and letting rcu_start_gp() start up the next grace period 1661 * period and letting rcu_start_gp() start up the next grace period