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 | |
| 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>
| -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 |
