From: Vineet Gupta <vineet.gupta@linux.dev>
To: rostedt@goodmis.org, mhiramat@kernel.org
Cc: mark.rutland@arm.com, mathieu.desnoyers@efficios.com,
andrii@kernel.org, peterz@infradead.org,
linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org, kernel-team@meta.com,
Vineet Gupta <vineet.gupta@linux.dev>
Subject: [PATCH 2/2] tracing: fgraph: Add a cond_resched() to the shadow stack retry loop
Date: Tue, 22 Sep 2026 15:55:26 -0700 [thread overview]
Message-ID: <20260922225526.1554758-3-vineet.gupta@linux.dev> (raw)
In-Reply-To: <20260922225526.1554758-1-vineet.gupta@linux.dev>
This is supplementary to previous patch and is effective only for
!PREEMPTION kernels.
The preceding patch cuts the number of sweeps over the thread list by
32x, but the loop is still O(N^2). Each pass walks from the same start
init_task under rcu_read_lock() with no reschedule point. On a kernel
that cannot preempt the walk, a large enough thread count lets one task
monopolize a CPU until the walk completes.
Add a cond_resched() between sweeps which is safe since it is outside
the RCU read-side critical section.
It is understood that this is effectively a no-op for CONFIG_PREEMPTION
builds, which is what default x86 and arm64 kernels are today.
A CONFIG_PREEMPT_DYNAMIC build with "preempt={none,voluntary}"
used to work but even that got inhibited since the commit
7dadeaa6e851 ("sched: Further restrict the preemption modes").
Measured on a 60-core machine with a PREEMPT_LAZY kernel and 400000
idle threads, this patch changes neither the runtime nor the yield
count, which stays at zero.
Where it does have effect is !CONFIG_PREEMPTION builds: architectures
that still offer PREEMPT_NONE or PREEMPT_VOLUNTARY, and the stable
kernels where x86 PREEMPT_NONE remains a build-time choice. Verified
on a 6.16 PREEMPT_NONE kernel, 240000 idle threads, three runs each,
with the loop instrumented to count passes and cond_resched() yields:
time yields soft lockup
unpatched 51.3-54.6 s - 3 of 3
cond_resched() 52.7-53.0 s 592-609 0 of 3
The runtime is unchanged and the soft lockups are gone. Every
need_resched() converts to a yield, giving an average of about 98 ms
between reschedules.
There is a second effect on those builds. When cond_resched() does not
reschedule it still calls rcu_all_qs() on !CONFIG_PREEMPT_RCU kernels,
reporting a quiescent state. So the two failures seen in the field are
addressed by two mechanisms: the soft lockup by yielding so the
watchdog can run, and the RCU stall by reporting a quiescent state
even on passes where no yield happens.
This is deliberately separable from the preceding patch. If the view
is that a no-op on the architectures anyone runs is not worth carrying,
dropping this one leaves the batch-size fix intact.
Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
kernel/trace/fgraph.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index ed455b53513b..86d11217c584 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -1249,6 +1249,14 @@ static int start_graph_tracing(void)
do {
ret = alloc_retstack_tasklist(ret_stack_list);
+ /*
+ * Each pass rescans the thread list from the head, so the
+ * loop is O(threads^2) overall. The RCU read-side section
+ * ends with the pass, and both locks held here (ftrace_lock,
+ * and fprobe_mutex for fprobe users) are mutexes, so it is
+ * safe to give the CPU up in between.
+ */
+ cond_resched();
} while (ret == -EAGAIN);
if (!ret) {
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-22 22:55 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 22:55 [PATCH 0/2] tracing: fgraph: cut the cost of " Vineet Gupta
2026-09-22 22:55 ` [PATCH 1/2] tracing: fgraph: Raise FTRACE_RETSTACK_ALLOC_SIZE to 1024 Vineet Gupta
2026-09-22 22:55 ` Vineet Gupta [this message]
2026-09-23 8:47 ` [PATCH 2/2] tracing: fgraph: Add a cond_resched() to the shadow stack retry loop Steven Rostedt
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=20260922225526.1554758-3-vineet.gupta@linux.dev \
--to=vineet.gupta@linux.dev \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®