From: Andrea Righi <arighi@nvidia.com>
To: Tejun Heo <tj@kernel.org>
Cc: David Vernet <void@manifault.com>,
Changwoo Min <changwoo@igalia.com>,
John Stultz <jstultz@google.com>, Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <peterz@infradead.org>,
Juri Lelli <juri.lelli@redhat.com>,
Vincent Guittot <vincent.guittot@linaro.org>,
Dietmar Eggemann <dietmar.eggemann@arm.com>,
Steven Rostedt <rostedt@goodmis.org>,
Ben Segall <bsegall@google.com>, Mel Gorman <mgorman@suse.de>,
Valentin Schneider <vschneid@redhat.com>,
K Prateek Nayak <kprateek.nayak@amd.com>,
Christian Loehle <christian.loehle@arm.com>,
David Dai <david.dai@linux.dev>, Koba Ko <kobak@nvidia.com>,
Aiqun Yu <aiqun.yu@oss.qualcomm.com>,
sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 12/17] sched_ext: Handle proxy-exec races in remote DSQ transfers
Date: Mon, 17 Aug 2026 21:32:38 +0200 [thread overview]
Message-ID: <aoNh1gAh1e8zDRKD@gpd4> (raw)
In-Reply-To: <aoNCIwlkVXKNgM5l@slm.duckdns.org>
On Mon, Aug 17, 2026 at 07:17:23AM -1000, Tejun Heo wrote:
> Hello,
>
> On Mon, Aug 17, 2026 at 09:15:22AM +0200, Andrea Righi wrote:
> > > > @@ -1530,12 +1539,17 @@ static void rq_owned_post_enq(struct scx_sched *sch, struct rq *rq,
> > > > call_task_dequeue(sch, rq, p, 0);
> > > >
> > > > /*
> > > > - * Only local inserts get the wakeup treatment below. Rejects kick the
> > > > - * deferred reenq and rescue parks are paced by the rescue timer.
> > > > + * Only local inserts get the wakeup treatment below. Proxy-active tasks
> > > > + * and rescuees remain parked until their respective resolution paths.
> > > > + * Other rejects can be reenqueued immediately.
> > > > */
> > > > if (unlikely(dsq->id != SCX_DSQ_LOCAL)) {
> > > > - if (dsq->id == SCX_DSQ_REJECT)
> > > > + if (dsq->id == SCX_DSQ_REJECT) {
> > > > + if ((p->scx.flags & SCX_TASK_REENQ_REASON_MASK) ==
> > > > + SCX_TASK_REENQ_PROXY)
> > > > + rq->scx.flags |= SCX_RQ_PROXY_REENQ;
> > >
> > > and if my reading above is correct, this wouldn't be necessary, right?
> >
> > The flag isn't needed to provide the post-switch ordering, but it is needed to
> > record that reject_dsq still needs another drain.
>
> But wouldn't it be able to use the same schedule_deferred_locked() call like
> SCX_DSQ_REJECT case so that the PROXY_REENQ flag is only used for retry
> cases (and maybe renamed accordingly)?
Yes. The initial insertion into reject_dsq can use schedule_deferred_locked()
without setting a proxy-specific flag. Then we can set the flag only when
scx_reenq_reject() actually skips a task because it is still running or
donating. How about renaming to SCX_RQ_PROXY_RETRY to refelct the new meaning?
>
> ...
> > It also preserves the outstanding drain if proxy re-pick calls
> > zap_balance_callbacks() before the initially queued callback runs. In
> > that case, the task is already parked on reject_dsq, but the flag lets
> > scx_proxy_resolved() queue replacement deferred work.
>
> I think this is a generic problem with core scheduling. SCX assumes that
> deferred scheduilng always runs but core-sched can zap them. We probably
> need to address this directly using a similar but generic deferred work
> pending flag.
Agreed. This isn't specific to proxy-rejected tasks, any sched_ext deferred work
queued through a balance callback can be lost if core scheduling zaps the
callback.
Maybe we can introduce a new generic sched_ext deferred work pending flag, kept
set until the deferred work actually runs and we can use it to rearm it after
callback cancellation?
Probably something to do for another patch series...
>
> > > > +{
> > > > + lockdep_assert_rq_held(rq);
> > > > + WARN_ON_ONCE((p->scx.flags & SCX_TASK_REENQ_REASON_MASK) &&
> > > > + !(enq_flags & SCX_ENQ_REENQ));
> > >
> > > In the previous patch, is it possible to clear reason before reenqueueing
> > > it and get rid of overwrite cases or does that quite not work out?
> >
> > Yes, I think we can get rid of the overwrite cases. There is one constraint,
> > though: the reason must remain set while ops.enqueue() runs, because BPF reads
> > it from p->scx.flags.
> >
> > I'll move the clearing into scx_do_enqueue_task() so that it happens immediately
> > after ops.enqueue() returns and before resolving any direct dispatch requested
> > by the callback. A rejection caused by that new placement will then see a clear
> > reason field and can set its own reason without overwriting the previous one.
>
> I haven't really thought through it so please do whatever that makes the
> code least ugly.
Ok, probably moving the clearing into scx_do_enqueue_task(), after ops.enqueue()
returns but before resolving the resulting placement is the least ugly way...
This keeps the reason visible to BPF while ensuring that a subsequent rejection
starts with a clear reason field.
>
> > > > @@ -2633,6 +2719,19 @@ static struct rq *move_task_between_dsqs(struct scx_sched *sch,
> > > >
> > > > if (dst_dsq->id == SCX_DSQ_LOCAL) {
> > > > dst_rq = container_of(dst_dsq, struct rq, scx.local_dsq);
> > > > + /*
> > > > + * Unlike the rq-lock handoff paths, @src_rq has been locked
> > > > + * throughout this operation. Only active proxy state can race the
> > > > + * move here; let the enforcing check below diagnose an ordinary
> > > > + * migration-disabled task.
> > > > + */
> > > > + proxy_raced = src_rq != dst_rq && task_proxy_move_active(p);
> > > > + if (unlikely(proxy_raced)) {
> > >
> > > I don't know what bouncing through the local var buys. Out of curiosity, if
> > > task_move_proxy_raced() is used here, does something break or is it just to
> > > avoid unnecessary tests?
> >
> > Yeah, the local variable doesn't buy anything, I'll remove it.
> >
> > Using task_move_proxy_raced() (aka task_proxy_unsafe_to_move() after the rename)
> > would change the behavior for an ordinary migration-disabled task. This path
> > holds src_rq, so that state isn't a lock-handoff race and should still reach
> > task_can_run_on_remote_rq(..., true), which diagnoses the invalid BPF-directed
> > migration. Treating it as a proxy rejection instead could hide that error and
> > cause repeated reenqueues.
>
> That sounds like something which is worth noting in the comment. It's subtle
> that this site needs a different set of conditions.
Agreed. I'll remove the local variable and expand the comment.
Thanks for all the help! Really appreciated!
-Andrea
next prev parent reply other threads:[~2026-08-17 19:32 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-16 17:34 [PATCHSET v12 sched_ext/for-7.3] sched: Make proxy execution compatible with sched_ext Andrea Righi
2026-08-16 17:34 ` [PATCH 01/17] sched/core: Drop mutex locks before proxy rescheduling Andrea Righi
2026-08-16 17:35 ` [PATCH 02/17] sched/core: Dequeue waking proxy donors before reset Andrea Righi
2026-08-16 20:20 ` Tejun Heo
2026-08-16 21:56 ` [PATCH v2] " Andrea Righi
2026-08-16 17:35 ` [PATCH 03/17] sched: Make NOHZ CFS bandwidth checks follow proxy donor Andrea Righi
2026-08-16 17:35 ` [PATCH 04/17] sched/core: Avoid false migration warning for proxy donors Andrea Righi
2026-08-16 17:35 ` [PATCH 05/17] sched: Pass next class to sched_change_begin() Andrea Righi
2026-08-16 17:35 ` [PATCH 06/17] sched: Add helper to block retained proxy donors Andrea Righi
2026-08-16 17:35 ` [PATCH 07/17] sched: Add sched_ext hooks for proxy execution Andrea Righi
2026-08-16 17:35 ` [PATCH 08/17] sched_ext: Block proxy donors across scheduler transitions Andrea Righi
2026-08-16 21:32 ` Tejun Heo
2026-08-16 22:06 ` Andrea Righi
2026-08-16 17:35 ` [PATCH 09/17] sched_ext: Fix ops.running/stopping() pairing for proxy-exec donors Andrea Righi
2026-08-16 22:10 ` Tejun Heo
2026-08-16 22:21 ` Andrea Righi
2026-08-16 22:29 ` [PATCH v2] " Andrea Righi
2026-08-16 17:35 ` [PATCH 10/17] sched_ext: Move reject DSQ draining into core Andrea Righi
2026-08-16 17:35 ` [PATCH 11/17] sched_ext: Generalize the reject DSQ reenqueue path Andrea Righi
2026-08-16 22:45 ` Tejun Heo
2026-08-17 6:29 ` Andrea Righi
2026-08-16 17:35 ` [PATCH 12/17] sched_ext: Handle proxy-exec races in remote DSQ transfers Andrea Righi
2026-08-16 23:54 ` Tejun Heo
2026-08-17 7:15 ` Andrea Righi
2026-08-17 17:17 ` Tejun Heo
2026-08-17 19:32 ` Andrea Righi [this message]
2026-08-17 19:49 ` Tejun Heo
2026-08-16 17:35 ` [PATCH 13/17] sched_ext: Split curr|donor references properly Andrea Righi
2026-08-16 17:35 ` [PATCH 14/17] sched_ext: Delegate proxy donor admission to BPF schedulers Andrea Righi
2026-08-17 3:02 ` Tejun Heo
2026-08-17 19:02 ` Andrea Righi
2026-08-17 20:24 ` Tejun Heo
2026-08-16 17:35 ` [PATCH 15/17] sched_ext: Add selftest for blocked donor admission Andrea Righi
2026-08-16 17:35 ` [PATCH 16/17] sched_ext: scx_qmap: Add proxy execution support Andrea Righi
2026-08-16 17:35 ` [PATCH 17/17] sched: Allow enabling proxy exec with sched_ext Andrea Righi
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=aoNh1gAh1e8zDRKD@gpd4 \
--to=arighi@nvidia.com \
--cc=aiqun.yu@oss.qualcomm.com \
--cc=bsegall@google.com \
--cc=changwoo@igalia.com \
--cc=christian.loehle@arm.com \
--cc=david.dai@linux.dev \
--cc=dietmar.eggemann@arm.com \
--cc=jstultz@google.com \
--cc=juri.lelli@redhat.com \
--cc=kobak@nvidia.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sched-ext@lists.linux.dev \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=void@manifault.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox