From: sashiko-bot@kernel.org
To: "Tejun Heo" <tj@kernel.org>, sched-ext@lists.linux.dev
Subject: Re: [PATCH 08/18] sched_ext: Fix a cpu idling with a runnable rescuee
Date: Tue, 27 Oct 2026 00:34:25 +0000 [thread overview]
Message-ID: <sashiko-outbox-185952@kernel.org> (raw)
In-Reply-To: <20261027001749.1821379-9-tj@kernel.org>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] sched_ext: premature slice restore in dispatch_one() via scx_rescue_keep()
--
commit 84249cc9d9822a67a9e62226f4711cf219c9db29
Author: Tejun Heo <tj@kernel.org>
sched_ext: Fix a cpu idling with a runnable rescuee
This commit fixes a bug where a CPU idles with a runnable rescuee when a
scheduler zeroes the rescuee's slice without dispatching another task, by
calling scx_rescue_keep() in dispatch_one() to keep the rescuee running on
its unserved remainder when nothing else is runnable.
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index 56742d1ce5131..2504a6a9911b3 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -3396,6 +3396,34 @@ static enum scx_dsp_verdict dispatch_one(struct rq *rq, struct task_struct *prev
> verdict = SCX_DSP_PREV;
> goto has_tasks;
> }
> +
> + /*
> + * The scheduler preempts a rescuee like any other task by
> + * zeroing its slice. The grant survives the preemption. The
> + * rescuee gets the unserved remainder back and runs again
> + * behind whatever the scheduler wanted to run first.
> + *
> + * Two sites restore the remainder. When another task won the
> + * pick, put_prev_task_scx() restores it and queues the rescuee
> + * at the tail of the local DSQ.
> + *
> + * When nothing else is runnable, the cpu must not go idle with
> + * the rescuee queued. The keep above takes a rescuee whose
> + * scheduler holds %SCX_CAP_BASE here and doesn't take the last
> + * task through %SCX_OPS_ENQ_LAST.
> + *
> + * The pick then ends its zeroed slice, and the rescue with it,
> + * and refills a default slice. The task continues as an
> + * ordinary one, which is fine as its scheduler holds BASE here.
> + *
> + * For any other rescuee, a reinsert from put_prev_task_scx()
> + * would come after the pick settled on idle. Keep it running on
> + * the remainder here.
> + */
> + if (unlikely(prev == scx_rescuee(rq)) && scx_rescue_keep(rq, prev)) {
> + verdict = SCX_DSP_PREV;
> + goto has_tasks;
> + }
[Severity: Medium]
Can calling scx_rescue_keep() inside dispatch_one() restore prev->scx.slice
prematurely when the pick is subsequently retried or aborted?
On the existing keep-last path right above this block, dispatch_one()
returns SCX_DSP_PREV while leaving prev->scx.slice at 0, and
do_pick_task_scx() only commits to ending and refilling the slice after
checking for retries and higher-priority class modifications:
kernel/sched/ext/ext.c:do_pick_task_scx() {
...
if (verdict == SCX_DSP_RETRY)
return RETRY_TASK;
...
if (!force_scx && rq_modified_above(rq, &ext_sched_class)) {
p = RETRY_TASK;
goto out;
}
if (verdict == SCX_DSP_PREV) {
p = prev;
if (!p->scx.slice) {
/* the slice is consumed, protection ends */
scx_task_slice_ended(rq, p);
refill_task_slice_dfl(scx_task_sched(p), p);
}
...
}
By contrast, calling scx_rescue_keep(rq, prev) in dispatch_one() writes
prev->scx.slice = remaining (> 0) before the pick is finalized. If
scx_dispatch_sched() temporarily dropped the rq lock before returning
SCX_DSP_NONE, two issues can occur:
1. Under core scheduling, dispatch_core_pick() sees that the rq lock was
dropped and discards the verdict:
kernel/sched/ext/ext.c:dispatch_core_pick() {
...
verdict = dispatch_one(rq, prev);
/* if dispatch_one() released the rq lock, restart the selection */
if (rq->scx.lock_drop_seq != seq)
return SCX_DSP_RETRY;
}
When the pick restarts and calls dispatch_one(rq, prev) again,
prev->scx.slice is now non-zero, so dispatch_one() short-circuits at the
top:
kernel/sched/ext/ext.c:dispatch_one() {
...
if ((prev->scx.flags & SCX_TASK_QUEUED) && prev->scx.slice &&
!scx_bypassing(scx_task_sched(prev), cpu)) {
verdict = SCX_DSP_PREV;
goto has_tasks;
}
}
This returns SCX_DSP_PREV before checking rq->scx.local_dsq.nr or calling
scx_dispatch_sched(), ignoring any tasks enqueued while the rq lock was
dropped.
2. If a higher-priority task (such as RT, DL, or fair) woke up while the rq
lock was dropped, do_pick_task_scx() sees rq_modified_above() and returns
RETRY_TASK (or core-sched cookie matching selects another task or
rq->idle). When put_prev_task_scx() then runs for prev, p->scx.slice is
already non-zero:
kernel/sched/ext/ext.c:put_prev_task_scx() {
...
if (!p->scx.slice) {
if (unlikely(p == scx_rescuee(rq)))
rescue_keep = scx_rescue_keep(rq, p);
if (!rescue_keep)
scx_task_slice_ended(rq, p);
}
...
if (p->scx.slice && !scx_bypassing(sch, cpu_of(rq))) {
...
if (unlikely(p == scx_rescuee(rq))) {
enq_flags |= SCX_ENQ_IGNORE_CAPS;
if (!rescue_keep)
enq_flags |= SCX_ENQ_HEAD;
}
}
Because !p->scx.slice is skipped, rescue_keep remains false and the
preempted rescuee is queued with SCX_ENQ_HEAD instead of at the tail of
the local DSQ.
Should the slice restoration via scx_rescue_keep() be deferred to the
verdict == SCX_DSP_PREV && !p->scx.slice block in do_pick_task_scx(), with
dispatch_one() only checking whether the rescuee can be kept (for example,
scx_rescue_slice_remaining(rq) > 0 && !scx_bypassing(prev_sch, cpu))?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261027001749.1821379-1-tj@kernel.org?part=8
next prev parent reply other threads:[~2026-10-27 0:34 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 0:17 [PATCHSET v4 sched_ext/for-7.4-fixes] sched_ext: Fix bypassed sub-scheduler tasks stalling when the host lacks caps Tejun Heo
2026-10-27 0:17 ` [PATCH 01/18] sched_ext: Pack scx_ent_flags' multi-bit fields at the top Tejun Heo
2026-10-27 0:17 ` [PATCH 02/18] sched_ext: Clear holding_cpu where the claim is confirmed Tejun Heo
2026-10-27 0:17 ` [PATCH 03/18] sched_ext: Fix bypassed tasks stranded by the reenqueue limit Tejun Heo
2026-10-27 0:17 ` [PATCH 04/18] sched_ext: Fix bypassed tasks looping on a host without SCX_CAP_ENQ Tejun Heo
2026-10-27 0:17 ` [PATCH 05/18] sched_ext: Move refill_task_slice_dfl() below apply_slice_vtime() Tejun Heo
2026-10-27 0:17 ` [PATCH 06/18] sched_ext: Fix rescue served time disagreeing with the slice under proxy execution Tejun Heo
2026-10-27 0:17 ` [PATCH 07/18] sched_ext: Restore a rescuee's slice after ops.stopping() Tejun Heo
2026-10-27 0:17 ` [PATCH 08/18] sched_ext: Fix a cpu idling with a runnable rescuee Tejun Heo
2026-10-27 0:34 ` sashiko-bot [this message]
2026-10-27 14:08 ` Tejun Heo
2026-10-27 0:17 ` [PATCH 09/18] sched_ext: Mark the rescue grant as a kernel slice with SCX_TASK_KERNEL_SLICE Tejun Heo
2026-10-27 0:17 ` [PATCH 10/18] sched_ext: Refuse extending a kernel slice Tejun Heo
2026-10-27 0:17 ` [PATCH 11/18] sched_ext: Fix a cpu idling after put_prev_task_scx() queues its task on the local DSQ Tejun Heo
2026-10-27 0:17 ` [PATCH 12/18] sched_ext: Expire prev's slice in dispatch_one() under bypass Tejun Heo
2026-10-27 0:17 ` [PATCH 13/18] sched_ext: Fix bypassed tasks stalling when the host lacks SCX_CAP_BASE Tejun Heo
2026-10-27 0:44 ` sashiko-bot
2026-10-27 14:08 ` Tejun Heo
2026-10-27 0:17 ` [PATCH 14/18] sched_ext: Fix the bypass load balancer stranding tasks on cpus where " Tejun Heo
2026-10-27 0:17 ` [PATCH 15/18] sched_ext: Factor out bypass_lb_move() and insert with the donor DSQ unlocked Tejun Heo
2026-10-27 0:17 ` [PATCH 16/18] sched_ext: Let the bypass load balancer move tasks homed on other cpus Tejun Heo
2026-10-27 0:17 ` [PATCH 17/18] sched_ext: Fix queued bypassed tasks stalling when the host loses SCX_CAP_BASE Tejun Heo
2026-10-27 0:17 ` [PATCH 18/18] sched_ext: Fix a lone IMMED task waiting behind a kept prev Tejun Heo
2026-10-27 14:08 ` [PATCH 19/18] sched_ext: Fix use-after-free of a NONE rescuee leaving its sched while running Tejun Heo
2026-10-27 14:08 ` [PATCH 20/18] sched_ext: Fix the rescue overload pick ejecting the wrong sub under bypass Tejun Heo
2026-10-27 19:11 ` [PATCHSET v4 sched_ext/for-7.4-fixes] sched_ext: Fix bypassed sub-scheduler tasks stalling when the host lacks caps Tejun Heo
2026-10-27 19:28 ` 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=sashiko-outbox-185952@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sched-ext@lists.linux.dev \
--cc=tj@kernel.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