* [PATCH sched_ext/for-7.3-fixes] sched_ext: Don't report a forced-idle CPU as open for IMMED tasks
@ 2026-10-17 12:47 Andrea Righi
2026-10-17 20:36 ` Tejun Heo
0 siblings, 1 reply; 3+ messages in thread
From: Andrea Righi @ 2026-10-17 12:47 UTC (permalink / raw)
To: Tejun Heo, David Vernet, Changwoo Min
Cc: Emil Tsalapatis, sched-ext, linux-kernel
Core scheduling can force a CPU idle while a higher-class task is
runnable on it: under an untagged core-wide max, an incompatible pick is
replaced with idle without looking for a compatible task; rq->next_class
is then idle, so rq_is_open() reports the CPU as open and IMMED tasks
inserted into its local DSQ are parked there behind the higher-class
task, instead of going back to the BPF scheduler.
This scenario was reproduced on an SMT pair with the ext server runtime
set to 0 on both siblings: an untagged SCHED_FIFO task spinning on one
sibling forced the other idle while a tagged SCHED_FIFO task was
runnable there. An IMMED task inserted into the local DSQ of the
forced-idle sibling was never reenqueued and stayed parked for the whole
test time window. With the ext server enabled the task eventually runs,
but only once the server kicks in, so far from immediate.
Fix by reporting the CPU as busy while the donor is idle and a higher
class is runnable, except during dispatch, where the higher classes had
nothing to run. With this change the IMMED task is reenqueued right away
and the BPF scheduler runs it on another CPU.
Fixes: 98d709cba319 ("sched_ext: Implement SCX_ENQ_IMMED")
Signed-off-by: Andrea Righi <arighi@nvidia.com>
---
kernel/sched/ext/ext.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index 6b472506944e9..4259578186954 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -336,6 +336,18 @@ static struct scx_dispatch_q *bypass_enq_target_dsq(struct scx_sched *sch, s32 c
return scx_bypass_dsq(scx_exec_sched(sch, cpu), cpu);
}
+static bool higher_class_runnable(struct rq *rq)
+{
+ if (sched_stop_runnable(rq))
+ return true;
+
+ /* The ext server selects SCX tasks ahead of RT and fair tasks. */
+ if (sched_dl_runnable(rq))
+ return rb_first_cached(&rq->dl.root) != &rq->ext_server.rb_node;
+
+ return sched_rt_runnable(rq) || sched_fair_runnable(rq);
+}
+
/**
* rq_is_open - Is the rq available for immediate execution of an SCX task?
* @rq: rq to test
@@ -357,6 +369,17 @@ static bool rq_is_open(struct rq *rq, u64 enq_flags)
if (sched_class_above(rq->next_class, &ext_sched_class))
return false;
+ /*
+ * Core scheduling can force @rq idle while a higher-class task is
+ * runnable on it. next_class is left at idle, or raised to ext by a
+ * local insertion, but the blocker is picked ahead of the local DSQ
+ * once the core cookie allows it. An in-progress dispatch means the
+ * higher classes had nothing to run.
+ */
+ if (rq->donor == rq->idle && !(rq->scx.flags & SCX_RQ_IN_DISPATCH) &&
+ higher_class_runnable(rq))
+ return false;
+
/*
* @rq is either in transition to or in idle and there is no
* higher-priority class task waking up on it.
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH sched_ext/for-7.3-fixes] sched_ext: Don't report a forced-idle CPU as open for IMMED tasks
2026-10-17 12:47 [PATCH sched_ext/for-7.3-fixes] sched_ext: Don't report a forced-idle CPU as open for IMMED tasks Andrea Righi
@ 2026-10-17 20:36 ` Tejun Heo
2026-10-17 21:30 ` Andrea Righi
0 siblings, 1 reply; 3+ messages in thread
From: Tejun Heo @ 2026-10-17 20:36 UTC (permalink / raw)
To: Andrea Righi
Cc: David Vernet, Changwoo Min, Emil Tsalapatis, sched-ext,
linux-kernel
Hello, Andrea.
On Sat, Oct 17, 2026 at 02:47:49PM +0200, Andrea Righi wrote:
> +static bool higher_class_runnable(struct rq *rq)
> +{
> + if (sched_stop_runnable(rq))
> + return true;
> +
> + /* The ext server selects SCX tasks ahead of RT and fair tasks. */
> + if (sched_dl_runnable(rq))
> + return rb_first_cached(&rq->dl.root) != &rq->ext_server.rb_node;
> +
> + return sched_rt_runnable(rq) || sched_fair_runnable(rq);
> +}
This duplicates the core pick order in sched_ext, the dl_server ordering
included, which is brittle. It also misses the case where the IMMED
task's own cookie forces the CPU idle, e.g. a tagged IMMED task while
the sibling runs an untagged RT task, as nothing above ext is runnable
on the CPU itself.
Instead of predicting the pick, how about reacting to it? A CPU picking
idle with IMMED tasks on its local DSQ means that they didn't run
immediately, whatever the reason. scx_update_idle() is already called on
every idle pick, from set_next_task_idle() on a task to idle switch and
from pick_task_idle() on an idle to idle re-pick, so maybe something
like the following in __scx_update_idle()?
if (idle && unlikely(rq->scx.nr_immed))
scx_schedule_reenq_local(rq, SCX_REENQ_...);
Outside forced idle, nr_immed should be zero there as pick_task_scx()
would have taken the local DSQ head. The reenq would need a flag telling
reenq_local() to skip rq_is_open(), as next_class is idle and the rq
would look open, keeping the IMMED task at the head.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH sched_ext/for-7.3-fixes] sched_ext: Don't report a forced-idle CPU as open for IMMED tasks
2026-10-17 20:36 ` Tejun Heo
@ 2026-10-17 21:30 ` Andrea Righi
0 siblings, 0 replies; 3+ messages in thread
From: Andrea Righi @ 2026-10-17 21:30 UTC (permalink / raw)
To: Tejun Heo
Cc: David Vernet, Changwoo Min, Emil Tsalapatis, sched-ext,
linux-kernel
Hi Tejun,
On Sat, Oct 17, 2026 at 10:36:19AM -1000, Tejun Heo wrote:
> Hello, Andrea.
>
> On Sat, Oct 17, 2026 at 02:47:49PM +0200, Andrea Righi wrote:
> > +static bool higher_class_runnable(struct rq *rq)
> > +{
> > + if (sched_stop_runnable(rq))
> > + return true;
> > +
> > + /* The ext server selects SCX tasks ahead of RT and fair tasks. */
> > + if (sched_dl_runnable(rq))
> > + return rb_first_cached(&rq->dl.root) != &rq->ext_server.rb_node;
> > +
> > + return sched_rt_runnable(rq) || sched_fair_runnable(rq);
> > +}
>
> This duplicates the core pick order in sched_ext, the dl_server ordering
> included, which is brittle. It also misses the case where the IMMED
> task's own cookie forces the CPU idle, e.g. a tagged IMMED task while
> the sibling runs an untagged RT task, as nothing above ext is runnable
> on the CPU itself.
Ah, right, a tagged IMMED task inserted on a CPU whose sibling runs an
untagged SCHED_FIFO task stays parked on the local DSQ with this patch
applied, which is wrong.
>
> Instead of predicting the pick, how about reacting to it? A CPU picking
> idle with IMMED tasks on its local DSQ means that they didn't run
> immediately, whatever the reason. scx_update_idle() is already called on
> every idle pick, from set_next_task_idle() on a task to idle switch and
> from pick_task_idle() on an idle to idle re-pick, so maybe something
> like the following in __scx_update_idle()?
>
> if (idle && unlikely(rq->scx.nr_immed))
> scx_schedule_reenq_local(rq, SCX_REENQ_...);
>
> Outside forced idle, nr_immed should be zero there as pick_task_scx()
> would have taken the local DSQ head. The reenq would need a flag telling
> reenq_local() to skip rq_is_open(), as next_class is idle and the rq
> would look open, keeping the IMMED task at the head.
Yeah, makes sense and it looks like a much more robust approach. I'll
send a new version that drops higher_class_runnable() and does this,
with an internal SCX_REENQ_IDLE_PICK (?) flag to make reenq_local() skip
rq_is_open().
Thanks for taking a look at this!
-Andrea
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-17 21:31 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 12:47 [PATCH sched_ext/for-7.3-fixes] sched_ext: Don't report a forced-idle CPU as open for IMMED tasks Andrea Righi
2026-10-17 20:36 ` Tejun Heo
2026-10-17 21:30 ` Andrea Righi
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.