From: Peter Zijlstra <peterz@infradead.org>
To: Tejun Heo <tj@kernel.org>
Cc: mingo@kernel.org, juri.lelli@redhat.com,
vincent.guittot@linaro.org, dietmar.eggemann@arm.com,
rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de,
vschneid@redhat.com, kprateek.nayak@amd.com,
linux-kernel@vger.kernel.org, ziqianlu@bytedance.com
Subject: Re: [PATCH v2 01/12] sched/core: Fix pick_next_task() self recursion
Date: Wed, 11 Nov 2026 11:45:21 +0100 [thread overview]
Message-ID: <20261111104521.GL2668200@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <69d54f4e77e99f41ea0fb22b7381a522@kernel.org>
On Tue, Nov 10, 2026 at 02:30:33PM -1000, Tejun Heo wrote:
> Hello, Peter.
>
> On Sat, Nov 07, 2026 at 12:59:14PM +0100, Peter Zijlstra wrote:
> > Since RETRY_TASK is only possible when a higher priority task gets enqueued
> > during the lock break, this must mean core_task_seq will also be incremented
> > and is thus completely covered by the seq number mismatch.
>
> This doesn't hold for sched_ext, which returns RETRY_TASK whenever
> dispatch released the rq lock, e.g. ops.dispatch() inserting a task into
> a remote CPU's local DSQ, with no enqueue or dequeue on this core.
>
> [ ... ]
>
> > if (!next->core_cookie) {
> > + /*
> > + * pick_task() can drop the core rq lock through
> > + * newidle balance. If a sibling established a
> > + * core-wide cookie while the lock was dropped, the
> > + * uncookied no-sync fast path is no longer valid.
> > + */
> > + if (unlikely(rq->core->core_cookie))
> > + goto restart;
> > +
> > rq->core_pick = NULL;
> > rq->core_dl_server = NULL;
>
> This only catches a sibling selection which has already committed. One
> still in flight has reset core_cookie to 0 and may have set this CPU's
> core_pick, which the fast path then clears without changing
> core_task_seq. It needs three or more SMT siblings (e.g. POWER), so it
> isn't a common case:
>
> 1. CPU2 is in the fast path and drops the lock in newidle.
> 2. CPU1 starts a core-wide selection: bumps core_task_seq, resets
> core_cookie, sets rq2->core_pick and drops the lock in
> pick_task(rq3).
> 3. CPU2 retakes the lock, sees core_cookie == 0, clears rq2->core_pick
> and commits.
> 4. CPU1 retakes the lock, passes the seq check and hands the NULL
> rq2->core_pick to cookie_equals().
>
> This becomes reachable with 10/12 ("sched/fair: Reflow pick_task_fair()
> / newidle"), where pick_task_fair() can drop the lock in newidle without
> returning RETRY_TASK, and reliably oopses in __schedule() on an SMT4 VM.
Nice find.
> One way could be bumping core_task_seq when the fast path commits after
> the seq moved, so that the in-flight selection restarts. Another would
> be testing seq != core_task_seq instead of core_cookie, at the cost of
> restarting on any enqueue or dequeue during the lock break.
It always did bother me this test wasn't the same we used below. Let
them both be: 'seq != rq->core->core_task_seq'.
> [ ... ]
>
> > p = pick_task(rq_i, rf);
> > - if (unlikely(p == RETRY_TASK)) {
> > + if (unlikely(seq != rq->core->core_task_seq ||
> > + WARN_ON_ONCE(p == RETRY_TASK))) {
>
> As sched_ext can return RETRY_TASK with core_task_seq unchanged, this
> triggers reliably with a BPF scheduler running cookied tasks. The
> restart is still correct. Can the WARN_ON_ONCE() be dropped? The plain
> RETRY_TASK test is still needed as the seq can match.
Sure, dropped the WARN.
---
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6391,13 +6391,7 @@ pick_next_task(struct rq *rq, struct rq_
}
if (!next->core_cookie) {
- /*
- * pick_task() can drop the core rq lock through
- * newidle balance. If a sibling established a
- * core-wide cookie while the lock was dropped, the
- * uncookied no-sync fast path is no longer valid.
- */
- if (unlikely(rq->core->core_cookie))
+ if (unlikely(seq != rq->core->core_task_seq))
goto restart;
rq->core_pick = NULL;
@@ -6431,8 +6425,7 @@ pick_next_task(struct rq *rq, struct rq_
update_rq_clock(rq_i);
p = pick_task(rq_i, rf);
- if (unlikely(seq != rq->core->core_task_seq ||
- WARN_ON_ONCE(p == RETRY_TASK))) {
+ if (unlikely(seq != rq->core->core_task_seq || p == RETRY_TASK)) {
/* rq lock may have been dropped, clocks invalidated */
core_clock_updated = false;
if (!(rq->clock_update_flags & RQCF_UPDATED))
next prev parent reply other threads:[~2026-11-11 10:45 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 11:59 [PATCH v2 00/12] sched: core-sched fixes and balancing Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 01/12] sched/core: Fix pick_next_task() self recursion Peter Zijlstra
2026-11-11 0:30 ` Tejun Heo
2026-11-11 10:45 ` Peter Zijlstra [this message]
2026-11-07 11:59 ` [PATCH v2 02/12] sched/core: Introduce rq_drop_lock() Peter Zijlstra
2026-11-08 9:25 ` Kayra Cizmeci
2026-11-11 10:46 ` Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 03/12] sched/core: Decompose update_rq_clock() Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 04/12] sched/core: Make __update_rq_clock() skip updates on UPDATED Peter Zijlstra
2026-11-11 1:11 ` Tejun Heo
2026-11-11 10:28 ` Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 05/12] sched/core: Abstract/fix rq_clock_start_loop_update() Peter Zijlstra
2026-11-08 22:26 ` Kayra Cizmeci
2026-11-11 9:10 ` K Prateek Nayak
2026-11-11 9:51 ` Kayra Cizmeci
2026-11-07 11:59 ` [PATCH v2 06/12] sched/core: New rq_{pin,drop,repin,unpin}_lock() semantics Peter Zijlstra
2026-11-11 10:41 ` Tejun Heo
2026-11-07 11:59 ` [PATCH v2 07/12] sched/core: Simplify/fix time updates Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 08/12] sched/core: Allow newidle for core-sched Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 09/12] sched/rt: Add early exit on balance path Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 10/12] sched/fair: Reflow pick_task_fair() / newidle Peter Zijlstra
2026-11-11 11:02 ` Tejun Heo
2026-11-07 11:59 ` [PATCH v2 11/12] sched/fair: Push sched_balance_newidle() unlock down Peter Zijlstra
2026-11-07 11:59 ` [PATCH v2 12/12] sched: Remove sched_class::balance() Peter Zijlstra
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=20261111104521.GL2668200@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=bsegall@google.com \
--cc=dietmar.eggemann@arm.com \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@kernel.org \
--cc=rostedt@goodmis.org \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=vschneid@redhat.com \
--cc=ziqianlu@bytedance.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 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®