[PATCH 18/18] sched_ext: Fix a lone IMMED task waiting behind a kept prev

From: Tejun Heo

Date: Mon Oct 26 2026 - 20:24:45 EST


While dispatch is in progress, rq_is_open() returns true and dsq_inc_nr()
schedules no reenqueue for an IMMED task inserted on an empty local DSQ. The
check at the end of dispatch_one() schedules the reenqueue only when more
than one task is queued, so a dispatch that keeps prev leaves a lone IMMED
task behind:

1. a parent's ops.dispatch() sub-dispatches into a child, which consumes a
task with SCX_ENQ_IMMED onto the empty local DSQ
2. the parent extends prev's slice and dispatch keeps prev
3. the local DSQ holds one task, so no reenqueue is scheduled

The IMMED task waits on the local DSQ behind prev.

Schedule the reenqueue when dispatch keeps prev and an IMMED task is queued,
as even a lone IMMED task can't run right away behind prev.

v2: The description and dispatch_one()'s comment are reworded.

Fixes: 98d709cba319 ("sched_ext: Implement SCX_ENQ_IMMED")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
---
kernel/sched/ext/ext.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index c7a5eba4b468..b7a78be01b42 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -3500,8 +3500,12 @@ static enum scx_dsp_verdict dispatch_one(struct rq *rq, struct task_struct *prev
*
* - A non-IMMED HEAD task can get queued in front of an IMMED task
* between the IMMED queueing and the subsequent scheduling event.
+ *
+ * - When dispatch keeps @prev, even a lone IMMED task queued during the
+ * dispatch can't run right away.
*/
- if (unlikely(rq->scx.local_dsq.nr > 1 && rq->scx.nr_immed))
+ if (unlikely((rq->scx.local_dsq.nr > 1 || verdict == SCX_DSP_PREV) &&
+ rq->scx.nr_immed))
scx_schedule_reenq_local(rq, 0);

rq->scx.flags &= ~SCX_RQ_IN_DISPATCH;
--
2.56.0