|
@@ -61,7 +61,7 @@ static struct lock_class_key rcu_root_class;
|
|
|
NUM_RCU_LVL_2, \
|
|
|
NUM_RCU_LVL_3, /* == MAX_RCU_LVLS */ \
|
|
|
}, \
|
|
|
- .signaled = RCU_SIGNAL_INIT, \
|
|
|
+ .signaled = RCU_GP_IDLE, \
|
|
|
.gpnum = -300, \
|
|
|
.completed = -300, \
|
|
|
.onofflock = __SPIN_LOCK_UNLOCKED(&name.onofflock), \
|
|
@@ -659,14 +659,17 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)
|
|
|
* irqs disabled.
|
|
|
*/
|
|
|
rcu_for_each_node_breadth_first(rsp, rnp) {
|
|
|
- spin_lock(&rnp->lock); /* irqs already disabled. */
|
|
|
+ spin_lock(&rnp->lock); /* irqs already disabled. */
|
|
|
rcu_preempt_check_blocked_tasks(rnp);
|
|
|
rnp->qsmask = rnp->qsmaskinit;
|
|
|
rnp->gpnum = rsp->gpnum;
|
|
|
- spin_unlock(&rnp->lock); /* irqs already disabled. */
|
|
|
+ spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
|
|
}
|
|
|
|
|
|
+ rnp = rcu_get_root(rsp);
|
|
|
+ spin_lock(&rnp->lock); /* irqs already disabled. */
|
|
|
rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state now OK. */
|
|
|
+ spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
|
|
spin_unlock_irqrestore(&rsp->onofflock, flags);
|
|
|
}
|
|
|
|
|
@@ -708,6 +711,7 @@ static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags)
|
|
|
{
|
|
|
WARN_ON_ONCE(!rcu_gp_in_progress(rsp));
|
|
|
rsp->completed = rsp->gpnum;
|
|
|
+ rsp->signaled = RCU_GP_IDLE;
|
|
|
rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]);
|
|
|
rcu_start_gp(rsp, flags); /* releases root node's rnp->lock. */
|
|
|
}
|
|
@@ -915,7 +919,20 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
|
|
|
spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
|
|
break;
|
|
|
}
|
|
|
- rcu_preempt_offline_tasks(rsp, rnp, rdp);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If there was a task blocking the current grace period,
|
|
|
+ * and if all CPUs have checked in, we need to propagate
|
|
|
+ * the quiescent state up the rcu_node hierarchy. But that
|
|
|
+ * is inconvenient at the moment due to deadlock issues if
|
|
|
+ * this should end the current grace period. So set the
|
|
|
+ * offlined CPU's bit in ->qsmask in order to force the
|
|
|
+ * next force_quiescent_state() invocation to clean up this
|
|
|
+ * mess in a deadlock-free manner.
|
|
|
+ */
|
|
|
+ if (rcu_preempt_offline_tasks(rsp, rnp, rdp) && !rnp->qsmask)
|
|
|
+ rnp->qsmask |= mask;
|
|
|
+
|
|
|
mask = rnp->grpmask;
|
|
|
spin_unlock(&rnp->lock); /* irqs remain disabled. */
|
|
|
rnp = rnp->parent;
|
|
@@ -1151,9 +1168,10 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
|
|
|
}
|
|
|
spin_unlock(&rnp->lock);
|
|
|
switch (signaled) {
|
|
|
+ case RCU_GP_IDLE:
|
|
|
case RCU_GP_INIT:
|
|
|
|
|
|
- break; /* grace period still initializing, ignore. */
|
|
|
+ break; /* grace period idle or initializing, ignore. */
|
|
|
|
|
|
case RCU_SAVE_DYNTICK:
|
|
|
|
|
@@ -1167,7 +1185,8 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
|
|
|
|
|
|
/* Update state, record completion counter. */
|
|
|
spin_lock(&rnp->lock);
|
|
|
- if (lastcomp == rsp->completed) {
|
|
|
+ if (lastcomp == rsp->completed &&
|
|
|
+ rsp->signaled == RCU_SAVE_DYNTICK) {
|
|
|
rsp->signaled = RCU_FORCE_QS;
|
|
|
dyntick_record_completed(rsp, lastcomp);
|
|
|
}
|