From: Peter Zijlstra <peterz@infradead.org>
To: Aaron Tomlin <atomlin@atomlin.com>
Cc: akpm@linux-foundation.org, mingo@redhat.com,
juri.lelli@redhat.com, vincent.guittot@linaro.org,
dietmar.eggemann@arm.com, rostedt@goodmis.org,
bsegall@google.com, mgorman@suse.de, vschneid@redhat.com,
feng.tang@linux.alibaba.com, pmladek@suse.com,
kprateek.nayak@amd.com, rishil1999@outlook.com,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] sched/debug, sys_info: Introduce SYS_INFO_CPU_RUNQUEUES
Date: Tue, 22 Sep 2026 16:40:27 +0200 [thread overview]
Message-ID: <20260922144027.GT776954@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20260912013240.545742-1-atomlin@atomlin.com>
On Fri, Sep 11, 2026 at 09:32:40PM -0400, Aaron Tomlin wrote:
> When investigating kernel panics, inspectability of per-CPU runqueues
> and runnable task states is valuable for diagnosing CPU starvation
> priority inversion, etc.
>
> While debugfs (/sys/kernel/debug/sched/debug) exposes runqueue metrics
> to userspace, these details are not captured during an automated kernel
> panic or crash dump. Capturing per-CPU runqueue state directly into
> log_buf fills this diagnostic gap for post-mortem crash analysis.
Uh, crash-dump preserves everything.
> rcu_read_lock();
> for_each_process_thread(g, p) {
> if (task_cpu(p) != rq_cpu)
> continue;
>
> - print_task(m, rq, p);
> + if (queued_only && !task_current(rq, p) && !task_on_rq_queued(p))
> + continue;
> +
> + print_task(m, rq, p, show_cgroup_path);
> }
> rcu_read_unlock();
> }
> @@ -1234,7 +1242,7 @@ do { \
> print_rt_stats(m, cpu);
> print_dl_stats(m, cpu);
>
> - print_rq(m, rq, cpu);
> + print_rq(m, rq, cpu, true, false);
> SEQ_printf(m, "\n");
> }
>
> @@ -1322,6 +1330,48 @@ void sysrq_sched_debug_show(void)
> }
> }
>
> +void sched_show_runqueues(void)
> +{
> + int cpu;
> +
> + pr_info("CPU Runqueues:\n");
> + for_each_online_cpu(cpu) {
> + struct rq *rq = cpu_rq(cpu);
> + struct task_struct *curr;
> + unsigned int nr_running;
> + u64 nr_switches;
> + unsigned long flags;
> + bool locked;
> +
> + touch_nmi_watchdog();
> + touch_all_softlockup_watchdogs();
> +
> + rcu_read_lock();
> + local_irq_save(flags);
> + locked = raw_spin_rq_trylock(rq);
> + if (locked) {
> + nr_running = rq->nr_running;
> + nr_switches = rq->nr_switches;
> + curr = rcu_dereference(rq->curr);
> + raw_spin_rq_unlock(rq);
> + } else {
> + nr_running = READ_ONCE(rq->nr_running);
> + nr_switches = READ_ONCE(rq->nr_switches);
> + curr = rcu_dereference(rq->curr);
> + }
> + local_irq_restore(flags);
This seems to want to avoid deadlocking on rq->lock, but then
print_rq()->print_cfs_stats() will unconditionally take rq->lock again.
So meh.
> +
> + pr_info("cpu#%d: nr_running:%u switches:%llu curr:%s[%d]%s\n",
> + cpu, nr_running, nr_switches,
> + curr ? curr->comm : "<none>",
> + curr ? task_pid_nr(curr) : -1,
> + locked ? "" : " (contended)");
> +
> + print_rq(NULL, rq, cpu, false, true);
> + rcu_read_unlock();
> + }
> +}
> +
> /*
> * This iterator needs some explanation.
> * It returns 1 for the header position.
> diff --git a/lib/sys_info.c b/lib/sys_info.c
> index f32a06ec9ed4..fc5bfcc121de 100644
> --- a/lib/sys_info.c
> +++ b/lib/sys_info.c
> @@ -22,6 +22,7 @@ static const char * const si_names[] = {
> [ilog2(SYS_INFO_PANIC_CONSOLE_REPLAY)] = "",
> [ilog2(SYS_INFO_ALL_BT)] = "all_bt",
> [ilog2(SYS_INFO_BLOCKED_TASKS)] = "blocked_tasks",
> + [ilog2(SYS_INFO_CPU_RUNQUEUES)] = "cpu_runqueues",
> };
>
> /*
> @@ -158,6 +159,9 @@ static void __sys_info(unsigned long si_mask)
>
> if (si_mask & SYS_INFO_BLOCKED_TASKS)
> show_state_filter(TASK_UNINTERRUPTIBLE);
> +
> + if (si_mask & SYS_INFO_CPU_RUNQUEUES)
> + sched_show_runqueues();
> }
I really don't know if this is worth the trouble. I have *never* needed
this.
next prev parent reply other threads:[~2026-09-22 14:40 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-12 1:32 [PATCH v2] sched/debug, sys_info: Introduce SYS_INFO_CPU_RUNQUEUES Aaron Tomlin
2026-09-22 14:31 ` Petr Mladek
2026-09-22 16:38 ` Aaron Tomlin
2026-09-22 14:40 ` Peter Zijlstra [this message]
2026-09-22 17:35 ` Aaron Tomlin
2026-09-23 8:37 ` Peter Zijlstra
2026-09-23 21:23 ` Aaron Tomlin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260922144027.GT776954@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=akpm@linux-foundation.org \
--cc=atomlin@atomlin.com \
--cc=bsegall@google.com \
--cc=dietmar.eggemann@arm.com \
--cc=feng.tang@linux.alibaba.com \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=pmladek@suse.com \
--cc=rishil1999@outlook.com \
--cc=rostedt@goodmis.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.