rcu: Make idle entry report expedited quiescent states
In non-preemptible kernels, an unfortunately timed expedited grace period can result in the rcu_exp_handler() IPI handler setting the rcu_data structure's cpu_no_qs.b.exp field just as the target CPU enters idle. There are situations in which this field will not be checked until after that CPU exits idle. The resulting grace-period latency does not qualify as "expedited". This commit therefore checks this field upon non-preemptible idle entry in the rcu_preempt_deferred_qs() function. It also qualifies the rcu_core() preempt_count() check with IS_ENABLED(CONFIG_PREEMPT_COUNT) to prevent false-positive quiescent states from count-free kernels. Reported-by: Neeraj Upadhyay <neeraju@codeaurora.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
parent
147f04b14a
commit
790da24897
|
@ -2714,7 +2714,7 @@ static __latent_entropy void rcu_core(void)
|
||||||
WARN_ON_ONCE(!rdp->beenonline);
|
WARN_ON_ONCE(!rdp->beenonline);
|
||||||
|
|
||||||
/* Report any deferred quiescent states if preemption enabled. */
|
/* Report any deferred quiescent states if preemption enabled. */
|
||||||
if (!(preempt_count() & PREEMPT_MASK)) {
|
if (IS_ENABLED(CONFIG_PREEMPT_COUNT) && (!(preempt_count() & PREEMPT_MASK))) {
|
||||||
rcu_preempt_deferred_qs(current);
|
rcu_preempt_deferred_qs(current);
|
||||||
} else if (rcu_preempt_need_deferred_qs(current)) {
|
} else if (rcu_preempt_need_deferred_qs(current)) {
|
||||||
set_tsk_need_resched(current);
|
set_tsk_need_resched(current);
|
||||||
|
|
|
@ -927,7 +927,18 @@ static bool rcu_preempt_need_deferred_qs(struct task_struct *t)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static void rcu_preempt_deferred_qs(struct task_struct *t) { }
|
|
||||||
|
// Except that we do need to respond to a request by an expedited grace
|
||||||
|
// period for a quiescent state from this CPU. Note that requests from
|
||||||
|
// tasks are handled when removing the task from the blocked-tasks list
|
||||||
|
// below.
|
||||||
|
static void rcu_preempt_deferred_qs(struct task_struct *t)
|
||||||
|
{
|
||||||
|
struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
|
||||||
|
|
||||||
|
if (rdp->cpu_no_qs.b.exp)
|
||||||
|
rcu_report_exp_rdp(rdp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Because there is no preemptible RCU, there can be no readers blocked,
|
* Because there is no preemptible RCU, there can be no readers blocked,
|
||||||
|
|
Loading…
Reference in New Issue