diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-12-31 05:24:21 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2013-03-26 11:04:58 -0400 |
commit | 910ee45db2f4837c8440e770474758493ab94bf7 (patch) | |
tree | dbc53615c3874cf1ea5588677e7b5f48462dcaff /kernel/rcutree.c | |
parent | 0446be489795d8bb994125a916ef03211f539e54 (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.c | 50 |
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; | |||
224 | module_param(jiffies_till_first_fqs, ulong, 0644); | 224 | module_param(jiffies_till_first_fqs, ulong, 0644); |
225 | module_param(jiffies_till_next_fqs, ulong, 0644); | 225 | module_param(jiffies_till_next_fqs, ulong, 0644); |
226 | 226 | ||
227 | static void rcu_start_gp(struct rcu_state *rsp); | 227 | static void rcu_start_gp_advanced(struct rcu_state *rsp, struct rcu_node *rnp, |
228 | struct rcu_data *rdp); | ||
228 | static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)); | 229 | static void force_qs_rnp(struct rcu_state *rsp, int (*f)(struct rcu_data *)); |
229 | static void force_quiescent_state(struct rcu_state *rsp); | 230 | static void force_quiescent_state(struct rcu_state *rsp); |
230 | static int rcu_pending(int cpu); | 231 | static 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 | } |
1167 | unlock_out: | 1168 | unlock_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 | */ |
1611 | static void | 1614 | static void |
1612 | rcu_start_gp(struct rcu_state *rsp) | 1615 | rcu_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 | */ | ||
1640 | static void | ||
1641 | rcu_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 |