A holdout that is running on a CPU with nothing else runnable is only preempted if the tick acts on rcu_request_urgent_qs_task()'s flag, and there may be no tick. Now that a preemption outside a trampoline is a quiescent state, have check_holdout_task() call resched_cpu() on a running holdout as well, so the scheduler IPIs it and it goes through __schedule() and reports (or, if it is inside a trampoline, does not report) its own state with purely local ordering. Nothing reads a running task's rcu_tramp_nesting remotely. Only under CONFIG_RCU_TASKS_PREEMPT_QS; other architectures are unchanged. Suggested-by: Paul E. McKenney Assisted-by: LLM Signed-off-by: Josef Bacik --- kernel/rcu/tasks.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h index ba432bd922e2..02d2592ab7a3 100644 --- a/kernel/rcu/tasks.h +++ b/kernel/rcu/tasks.h @@ -1038,8 +1038,18 @@ static bool rcu_tasks_preempted_qs(struct task_struct *t) { return task_call_func(t, rcu_tasks_switched_out_clean, NULL); } + +/* Make a running holdout pass through __schedule() soon, tick or no tick. */ +static void rcu_tasks_kick_running(struct task_struct *t) +{ + int cpu = task_cpu(t); + + if (task_curr(t) && cpu_online(cpu)) + resched_cpu(cpu); +} #else static bool rcu_tasks_preempted_qs(struct task_struct *t) { return false; } +static void rcu_tasks_kick_running(struct task_struct *t) { } #endif /* Per-task initial processing. */ @@ -1219,6 +1229,7 @@ static void check_holdout_task(struct task_struct *t, return; } rcu_request_urgent_qs_task(t); + rcu_tasks_kick_running(t); if (!needreport) return; if (*firstreport) { -- 2.55.0