From: sashiko-bot@kernel.org
To: "Andrea Righi" <arighi@nvidia.com>
Cc: sched-ext@lists.linux.dev
Subject: Re: [PATCH 11/15] sched_ext: Split curr|donor references properly
Date: Mon, 10 Aug 2026 16:06:29 +0000 [thread overview]
Message-ID: <20260810160630.58F1C1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260810151523.86994-12-arighi@nvidia.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] rq_is_open() incorrectly inspects rq->curr instead of rq->donor when evaluating SCX_ENQ_PREEMPT constraints.
- [High] scx_rescue_charge() misattributes rescue execution time by dereferencing scx_task_sched(rq->curr) instead of rq->donor.
- [Medium] dequeue_task_scx() and scx_bypass() incorrectly evaluate task_current() instead of task_current_donor().
- [Medium] Blocked proxy donors incorrectly enter ops.running() and ops.stopping() sessions, directly contradicting documentation.
--
--- Patch [11]: [PATCH 11/15] sched_ext: Split curr|donor references properly ---
commit 85eb7af3f37babba254fc28b03cd51fb5e7deb18
Author: Andrea Righi <arighi@nvidia.com>
sched_ext: Split curr|donor references properly
This commit updates sched_ext to correctly differentiate between the physical
execution task (rq->curr) and the scheduling context donor (rq->donor) during
proxy execution. It modifies scheduling policy and accounting paths to rely on
rq->donor, resolving discrepancies when the two tasks differ. It also extends
scx_dump_state() to explicitly report both contexts.
> diff --git a/Documentation/scheduler/sched-ext.rst b/Documentation/scheduler/sched-ext.rst
> index ad2fff3c05937..db1ef89ed8f2a 100644
> --- a/Documentation/scheduler/sched-ext.rst
> +++ b/Documentation/scheduler/sched-ext.rst
> @@ -487,6 +487,12 @@ and edge cases, to name a few examples:
> class, in which case it will exit the tick-dispatch loop even though it is runnable
> and has a non-zero slice.
>
> +* Under proxy execution, sched_ext continues to observe the donor as the current
> + scheduling context. A blocked donor does not enter an ``ops.running()`` /
> + ``ops.stopping()`` session because it does not execute itself, and the lock
> + owner executing on its behalf is intentionally not reported through these
> + callbacks.
> +
[Severity: Medium]
Will blocked proxy donors incorrectly enter ops.running() and ops.stopping()
sessions, contradicting this documentation?
In set_next_task_scx(), when restoring a previously resolved context (!first):
if ((p->scx.flags & SCX_TASK_QUEUED) && (!p->is_blocked || !first))
scx_start_task_running(rq, p);
And in scx_proxy_donor_start():
if (donor->sched_class == &ext_sched_class &&
(donor->scx.flags & SCX_TASK_QUEUED))
scx_start_task_running(rq, donor);
Does calling scx_start_task_running() unconditionally for queued donors here
mark the task with SCX_TASK_RUN_TRACKED and invoke the BPF running callbacks,
violating the API contract that blocked donors do not execute themselves?
> See the "Scheduling Cycle" section for a more detailed description of how
> a freshly woken up task gets on a CPU.
>
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index 7b467b666212b..39d3e3af05f90 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -1438,23 +1438,30 @@ static void apply_slice_vtime(struct task_struct *p, u64 slice, u64 vtime, u64 e
>
> static void update_curr_scx(struct rq *rq)
> {
> - struct task_struct *curr = rq->curr;
> + struct task_struct *donor;
> s64 delta_exec;
>
> + /*
> + * update_curr_scx() is selected through rq->donor->sched_class, not
> + * rq->curr->sched_class, so @donor is always an EXT task here. If an EXT
> + * owner executes for a FAIR donor, FAIR's update_curr() runs instead.
> + */
> + donor = rq->donor;
> +
> /* apply even on 0 delta_exec, callers may still act on the slice */
> - apply_task_slice_oob(rq, curr);
> + apply_task_slice_oob(rq, donor);
>
> delta_exec = update_curr_common(rq);
> if (unlikely(delta_exec <= 0))
> return;
>
> - if (curr->scx.slice != SCX_SLICE_INF) {
> - curr->scx.slice -= min_t(u64, curr->scx.slice, delta_exec);
> - if (!curr->scx.slice)
> - touch_core_sched(rq, curr);
> + if (donor->scx.slice != SCX_SLICE_INF) {
> + donor->scx.slice -= min_t(u64, donor->scx.slice, delta_exec);
> + if (!donor->scx.slice)
> + touch_core_sched(rq, donor);
> }
>
> - if (unlikely(curr == scx_rescuee(rq)))
> + if (unlikely(donor == scx_rescuee(rq)))
> scx_rescue_charge(rq, delta_exec);
[Severity: High]
Does scx_rescue_charge() misattribute rescue execution time by dereferencing
scx_task_sched(rq->curr) instead of rq->donor?
When a proxy donor is placed in the rescue DSQ and consumes time,
scx_rescue_charge() is called here, but internally it does:
pcpu = per_cpu_ptr(scx_task_sched(rq->curr)->pcpu, cpu_of(rq));
pcpu->rescue_avg = scx_rescue_decay_avg(pcpu) + delta_exec;
If rq->curr is a non-ext task (like fair), scx_task_sched() could return
incorrect scheduler contexts or default structures. Can this lead to accounting
corruption or potential pointer dereferences when it charges the consumed
budget to the physical execution task's scheduler instead of the ext donor?
>
> dl_server_update(&rq->ext_server, delta_exec);
[ ... ]
> @@ -1634,9 +1641,9 @@ static void rq_owned_post_enq(struct scx_sched *sch, struct rq *rq,
> if (rq->scx.flags & SCX_RQ_IN_BALANCE)
> return;
>
> - if ((enq_flags & SCX_ENQ_PREEMPT) && p != rq->curr &&
> - rq->curr->sched_class == &ext_sched_class) {
> - if (likely(scx_set_task_slice(rq->curr, 0)))
> + if ((enq_flags & SCX_ENQ_PREEMPT) && p != rq->donor &&
> + rq->donor->sched_class == &ext_sched_class) {
> + if (likely(scx_set_task_slice(rq->donor, 0)))
> resched_curr(rq);
> else
> __scx_add_event(sch, SCX_EV_SLICE_DENIED, 1);
[Severity: High]
Does rq_is_open() also need to check rq->donor instead of rq->curr when
evaluating SCX_ENQ_PREEMPT constraints?
Currently, rq_is_open() evaluates the physical execution task (rq->curr):
struct task_struct *curr = rq->curr;
return curr->sched_class != &ext_sched_class ||
likely(!(curr->scx.flags & SCX_TASK_PROTECTED));
Under proxy execution, if rq->curr is a fair task while the donor (rq->donor)
is an ext task with a protected slice, rq_is_open() would return true, causing
dsq_inc_nr() to queue an immed task assuming immediate preemption.
However, since rq_owned_post_enq() here correctly checks rq->donor and refuses
preemption, could this leave the newly queued task stranded on the local DSQ
without a reschedule kick, causing starvation?
[ ... ]
> @@ -2212,13 +2219,14 @@ static void enqueue_task_scx(struct rq *rq, struct task_struct *p, int core_enq_
> rq->scx.flags |= SCX_RQ_IN_WAKEUP;
>
> /*
> - * Restoring a running task will be immediately followed by
> - * set_next_task_scx() which expects the task to not be on the BPF
> + * Restoring the current scheduling context will be immediately followed
> + * by set_next_task_scx() which expects the task to not be on the BPF
> * scheduler as tasks can only start running through local DSQs. Force
> * direct-dispatch into the local DSQ by setting the sticky_cpu. Mark
> * IGNORE_CAPS to force entry into the local DSQ.
> */
> - if (unlikely(enq_flags & ENQUEUE_RESTORE) && task_current(rq, p)) {
> + if (unlikely(enq_flags & ENQUEUE_RESTORE) &&
> + task_current_donor(rq, p)) {
> sticky_cpu = cpu_of(rq);
> enq_flags |= SCX_ENQ_IGNORE_CAPS;
> }
[Severity: Medium]
Are there other places that should use task_current_donor() instead of
task_current() to avoid stripping the slice from the active proxy donor
prematurely?
For example, in dequeue_task_scx():
if (!((deq_flags & DEQUEUE_SAVE) && task_current(rq, p)))
scx_task_slice_ended(rq, p);
If a proxy donor is dequeued with DEQUEUE_SAVE (e.g. for a priority change),
the task_current(rq, p) check will fail because the physical execution task is
not the donor, causing the donor to lose its slice protection.
Similarly in scx_bypass():
if (bypass && task_current(rq, p))
scx_task_slice_ended(rq, p);
Could this fail to clear the slice for the active proxy donor because
task_current() evaluates to false?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260810151523.86994-1-arighi@nvidia.com?part=11
next prev parent reply other threads:[~2026-08-10 16:06 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-10 15:13 [PATCHSET v11 sched_ext/for-7.3] sched: Make proxy execution compatible with sched_ext Andrea Righi
2026-08-10 15:13 ` [PATCH 01/15] sched: Make NOHZ CFS bandwidth checks follow proxy donor Andrea Righi
2026-08-10 15:35 ` sashiko-bot
2026-08-10 15:13 ` [PATCH 02/15] sched/core: Avoid false migration warning for proxy donors Andrea Righi
2026-08-10 15:13 ` [PATCH 03/15] sched: Pass next class to sched_change_begin() Andrea Righi
2026-08-10 15:13 ` [PATCH 04/15] sched: Add helper to block retained proxy donors Andrea Righi
2026-08-10 15:13 ` [PATCH 05/15] sched: Add sched_ext hooks for proxy execution Andrea Righi
2026-08-10 15:13 ` [PATCH 06/15] sched_ext: Block proxy donors across scheduler transitions Andrea Righi
2026-08-10 15:13 ` [PATCH 07/15] sched_ext: Fix ops.running/stopping() pairing for proxy-exec donors Andrea Righi
2026-08-10 15:13 ` [PATCH 08/15] sched_ext: Move reject DSQ draining into core Andrea Righi
2026-08-10 15:13 ` [PATCH 09/15] sched_ext: Generalize the reject DSQ reenqueue path Andrea Righi
2026-08-10 15:55 ` sashiko-bot
2026-08-10 15:13 ` [PATCH 10/15] sched_ext: Handle proxy-exec races in remote DSQ transfers Andrea Righi
2026-08-10 16:04 ` sashiko-bot
2026-08-10 15:13 ` [PATCH 11/15] sched_ext: Split curr|donor references properly Andrea Righi
2026-08-10 16:06 ` sashiko-bot [this message]
2026-08-10 15:13 ` [PATCH 12/15] sched_ext: Delegate proxy donor admission to BPF schedulers Andrea Righi
2026-08-10 15:13 ` [PATCH 13/15] sched_ext: Add selftest for blocked donor admission Andrea Righi
2026-08-10 15:14 ` [PATCH 14/15] sched_ext: scx_qmap: Add proxy execution support Andrea Righi
2026-08-10 15:14 ` [PATCH 15/15] sched: Allow enabling proxy exec with sched_ext Andrea Righi
-- strict thread matches above, loose matches on Subject: below --
2026-07-28 15:43 [PATCHSET v10 sched_ext/for-7.3] sched: Make proxy execution compatible " Andrea Righi
2026-07-28 15:43 ` [PATCH 11/15] sched_ext: Split curr|donor references properly Andrea Righi
2026-07-28 16:25 ` sashiko-bot
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=20260810160630.58F1C1F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=arighi@nvidia.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sched-ext@lists.linux.dev \
/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 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.