Re: [PATCH] rcu: Print CPU that preempted stalled reader wants to run on

From: K Prateek Nayak

Date: Tue Oct 20 2026 - 23:49:30 EST


Hello Paul,

On 10/20/2026 2:17 AM, Paul E. McKenney wrote:
> This commit defines a cpu_curr_snapshot_rcu() function that invokes
> rcu_dereference_all(cpu_curr()) to determine which task is currently
> running on the specified CPU. The RCU CPU stall warning then uses this
> new function in order to print the task that has preempted the stalled
> task (the stalled task being the one that is in an RCU read-side critical
> section, thus preventing the current RCU grace period from completing).
> This modified stall-warning message also includes the CPU, along with
> an exclamation mark ("!") after the CPU number if that CPU is currently
> offline.
>
> This is a potential step towards allowing people (or LLMs, for that
> matter) locate any tasks that might be preventing the preempted RCU
> reader task from running.
>
> Adding a get_task_struct() for the currently running task would be a
> bug because we are not in a position to prevent that task from exiting.
> Yes, yes, because interrupts are disabled throughout, the corresponding
> task_struct structure cannot be freed, but following sequence of events
> is all too possible:
>
> o The check_slow_task() function places a pointer to the task_struct
> structure in its local variable "th".
>
> o The corresponding task exits, reducing its task_struct structure's
> ->usage to zero. The task_struct structure is therefore passed
> to call_rcu().
>
> o The check_slow_task() function invokes get_task_struct(th),
> setting th->usage to one.
>
> o The rcu_print_task_stall() function invokes put_task_struct(),
> again reducing ->usage to zero, and again passing the task
> struct to call_rcu(). This results in either double-call_rcu()
> or use-after-free, depending on when the RCU grace period for
> the first call_rcu() completes. Both outcomes are bad.
>
> This commit therefore relies solely on disabled interrupts acting as
> an implicit RCU read-side critical section that prevents all of the
> task_struct structures from being freed, thus avoiding the need for
> get_task_struct().
>
> The original get_task_struct() calls in rcu_print_task_stall() on the
> tasks on the ->blkd_tasks list are safe because those tasks cannot exit
> without first acquiring the rcu_node ->lock that this code already holds
> (because these tasks must remove themselves from the ->blkd_tasks list).
> But it is better to be consistent and rely on RCU in both cases.
> These pre-existing get_task_struct() and put_task_struct() calls are
> therefore removed.
>
> [ paulmck: Apply feedback from K Prateek Nayak and Peter Zijlstra. ]
> [ paulmck: Apply feedback from Steven Rostedt. ]
>
> Link: https://lore.kernel.org/all/a7a21bf3-a7d5-45bb-be4f-0119fe53fa20@paulmck-laptop/
> Link: https://lore.kernel.org/all/e8b6b372-d16b-4939-aa7a-755b7149e0fb@paulmck-laptop/
> Signed-off-by: Paul E. McKenney <paulmck@xxxxxxxxxx>
> Reviewed-by: Steven Rostedt <rostedt@xxxxxxxxxxx>

I tested this on your old dev branch on top of commit 5433117c67f0 ("EXP
rcutorture: Disable RCU priority boost testing on non-TREE03 scenarios")
and the idle state during stalls are reported correctly.

Feel free to include:

Reviewed-by: K Prateek Nayak <kprateek.nayak@xxxxxxx>
Tested-by: K Prateek Nayak <kprateek.nayak@xxxxxxx>

>
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 8b3d47a325cca..3606e5a2cec32 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -2532,3 +2532,5 @@ extern void migrate_enable(void);
> DEFINE_LOCK_GUARD_0(migrate, migrate_disable(), migrate_enable())
>
> #endif
> +
> +struct task_struct *cpu_curr_snapshot_rcu(int cpu);

nit.

I think this and the function definition in core.c can go right after
cpu_curr_snapshot() in respective files to keep the related bits
together.

--
Thanks and Regards,
Prateek