Skip to content

Commit 516e5ae

Browse files
joelagnelpaulmckrcu
authored andcommitted
rcu: Reset CPU hints when reporting a quiescent state
In some cases, tracing shows that need_heavy_qs is still set even though urgent_qs was cleared upon reporting of a quiescent state. One such case is when the softirq reports that a CPU has passed quiescent state. Commit 671a635 ("rcu: Avoid unnecessary softirq when system is idle") fixed a bug where core_needs_qs was not being cleared. In order to avoid running into similar situations with the urgent-grace-period flags, this commit causes rcu_disable_urgency_upon_qs(), previously rcu_disable_tick_upon_qs(), to clear the urgency hints, ->rcu_urgent_qs and ->rcu_need_heavy_qs. Note that it is possible for CPUs to go offline with these urgency hints still set. This is handled because rcu_disable_urgency_upon_qs() is also invoked during the online process. Because these hints can be cleared both by the corresponding CPU and by the grace-period kthread, this commit also adds a number of READ_ONCE() and WRITE_ONCE() calls. Tested overnight with rcutorture running for 60 minutes on all configurations of RCU. Signed-off-by: "Joel Fernandes (Google)" <[email protected]> [ paulmck: Clear urgency flags in rcu_disable_urgency_upon_qs(). ] [ paulmck: Remove ->core_needs_qs from the set cleared at quiescent state. ] [ paulmck: Make rcu_disable_urgency_upon_qs static per kbuild test robot. ] Signed-off-by: Paul E. McKenney <[email protected]>
1 parent b200a04 commit 516e5ae

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

kernel/rcu/tree.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,7 @@ static __always_inline void rcu_nmi_enter_common(bool irq)
827827
incby = 1;
828828
} else if (tick_nohz_full_cpu(rdp->cpu) &&
829829
rdp->dynticks_nmi_nesting == DYNTICK_IRQ_NONIDLE &&
830-
rdp->rcu_urgent_qs && !rdp->rcu_forced_tick) {
830+
READ_ONCE(rdp->rcu_urgent_qs) && !rdp->rcu_forced_tick) {
831831
rdp->rcu_forced_tick = true;
832832
tick_dep_set_cpu(rdp->cpu, TICK_DEP_BIT_RCU);
833833
}
@@ -892,11 +892,14 @@ void rcu_irq_enter_irqson(void)
892892
}
893893

894894
/*
895-
* If the scheduler-clock interrupt was enabled on a nohz_full CPU
896-
* in order to get to a quiescent state, disable it.
895+
* If any sort of urgency was applied to the current CPU (for example,
896+
* the scheduler-clock interrupt was enabled on a nohz_full CPU) in order
897+
* to get to a quiescent state, disable it.
897898
*/
898-
void rcu_disable_tick_upon_qs(struct rcu_data *rdp)
899+
static void rcu_disable_urgency_upon_qs(struct rcu_data *rdp)
899900
{
901+
WRITE_ONCE(rdp->rcu_urgent_qs, false);
902+
WRITE_ONCE(rdp->rcu_need_heavy_qs, false);
900903
if (tick_nohz_full_cpu(rdp->cpu) && rdp->rcu_forced_tick) {
901904
tick_dep_clear_cpu(rdp->cpu, TICK_DEP_BIT_RCU);
902905
rdp->rcu_forced_tick = false;
@@ -1997,7 +2000,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_data *rdp)
19972000
if (!offloaded)
19982001
needwake = rcu_accelerate_cbs(rnp, rdp);
19992002

2000-
rcu_disable_tick_upon_qs(rdp);
2003+
rcu_disable_urgency_upon_qs(rdp);
20012004
rcu_report_qs_rnp(mask, rnp, rnp->gp_seq, flags);
20022005
/* ^^^ Released rnp->lock */
20032006
if (needwake)
@@ -2311,7 +2314,7 @@ static void force_qs_rnp(int (*f)(struct rcu_data *rdp))
23112314
rdp = per_cpu_ptr(&rcu_data, cpu);
23122315
if (f(rdp)) {
23132316
mask |= bit;
2314-
rcu_disable_tick_upon_qs(rdp);
2317+
rcu_disable_urgency_upon_qs(rdp);
23152318
}
23162319
}
23172320
}
@@ -3182,7 +3185,7 @@ void rcu_cpu_starting(unsigned int cpu)
31823185
rdp->rcu_onl_gp_seq = READ_ONCE(rcu_state.gp_seq);
31833186
rdp->rcu_onl_gp_flags = READ_ONCE(rcu_state.gp_flags);
31843187
if (rnp->qsmask & mask) { /* RCU waiting on incoming CPU? */
3185-
rcu_disable_tick_upon_qs(rdp);
3188+
rcu_disable_urgency_upon_qs(rdp);
31863189
/* Report QS -after- changing ->qsmaskinitnext! */
31873190
rcu_report_qs_rnp(mask, rnp, rnp->gp_seq, flags);
31883191
} else {

0 commit comments

Comments
 (0)