From: bot+bpf-ci@kernel.org
To: cui.tao@linux.dev,tj@kernel.org
Cc: void@manifault.com,arighi@nvidia.com,changwoo@igalia.com,mingo@redhat.com,peterz@infradead.org,sched-ext@lists.linux.dev,linux-kernel@vger.kernel.org,bpf@vger.kernel.org,cui.tao@linux.dev,cuitao@kylinos.cn,ast@kernel.org,andrii@kernel.org,daniel@iogearbox.net,martin.lau@kernel.org,eddyz87@gmail.com,yonghong.song@linux.dev,mason@kernel.org,ihor.solodrai@linux.dev
Subject: Re: [PATCH 2/2] sched_ext: Block a retained donor before PI deboost routes it back to sched_ext
Date: Fri, 13 Nov 2026 03:05:14 +0000 (UTC) [thread overview]
Message-ID: <89f7ed00d7373ea7389e563810fbcd7ae775858e7fb592ad6e12cc1d1aee2565@mail.kernel.org> (raw)
In-Reply-To: <20261112144935.583937-3-cui.tao@linux.dev>
[-- Attachment #1: Type: text/plain, Size: 5395 bytes --]
> sched_ext: Block a retained donor before PI deboost routes it back to sched_ext
TL;DR:
- Possible WARN_ON_ONCE from a double rq clock update on every rt/dl to ext PI
deboost when WARN_DOUBLE_CLOCK is enabled
- Changelog's "only entry path" claim may be wrong: sched_setscheduler() can
also skip blocking donors
- Peter Zijlstra rejected this hook; is it still intended?
> sched_ext: Block a retained donor before PI deboost routes it back to sched_ext
>
> rt_mutex_setprio() is the only entry path into sched_ext that does not
> block a retained donor: an ext task PI-boosted by an rt waiter can
> block on a second kernel mutex while boosted, and on deboost is routed
> back to sched_ext carrying the queued+blocked state that
> scx_prepare_setscheduler() promises never happens; every PI cycle
> hands the BPF scheduler a queued+blocked donor it never admitted.
>
> Call scx_prepare_task_sched_change() before the sched_change guard when
> the class change routes the task back to sched_ext, which performs the
> missing sched_proxy_block_task() (plus an update_rq_clock() that is
> harmless here: the clock was already advanced, so the second advance
> only applies a small delta). The boost direction (ext -> rt) needs no
> handling.
>
> Fixes: be8be8acb268 ("sched_ext: Block proxy donors before taking control")
> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
The changelog says rt_mutex_setprio() is the only entry path into sched_ext
that does not block a retained donor. Is that accurate?
In __sched_setscheduler(), scx_prepare_setscheduler() only blocks the donor
when policy == SCHED_EXT. With a BPF scheduler loaded without
SCX_OPS_SWITCH_PARTIAL, task_should_scx() returns true for every policy, so
__setscheduler_class(SCHED_NORMAL, ...) returns &ext_sched_class.
That means sched_setscheduler(pid, SCHED_NORMAL) on a SCHED_FIFO or
SCHED_DEADLINE task that is being retained as a mutex-blocked donor routes it
into sched_ext without scx_block_proxy_donor() being called. The same
applies to normalize_rt_tasks() via sysrq-n.
The new comment in rt_mutex_setprio() also says "the same way the other entry
points into sched_ext do".
Should scx_prepare_setscheduler() be keyed on the resulting class like the new
check, or should the changelog be reworded?
> diff --git a/kernel/sched/core.c b/kernel/sched/core.c
> index f7a452123ef5..dcb16b006740 100644
> --- a/kernel/sched/core.c
> +++ b/kernel/sched/core.c
[ ... ]
> @@ -7816,6 +7816,18 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
> if (prev_class != next_class)
> queue_flag |= DEQUEUE_CLASS;
>
> + /*
> + * PI boost can route @p out of sched_ext: policy stays SCHED_EXT but
> + * __setscheduler_class() follows the effective rt prio, and rt/fair
> + * may have retained @p on the rq as a blocked donor. Block it before
> + * sched_change_begin() records the queued state, the same way the
> + * other entry points into sched_ext do.
> + */
> +#ifdef CONFIG_SCHED_CLASS_EXT
> + if ((queue_flag & DEQUEUE_CLASS) && next_class == &ext_sched_class)
> + scx_prepare_task_sched_change(p);
> +#endif
rt_mutex_setprio() has already called update_rq_clock() after taking the rq
lock, and the rq is not unpinned in between, so RQCF_UPDATED is still set.
scx_prepare_task_sched_change() then calls update_rq_clock(task_rq(p))
unconditionally, before checking whether @p is a retained donor.
update_rq_clock() does:
if (sched_feat(WARN_DOUBLE_CLOCK))
WARN_ON_ONCE(rq->clock_update_flags & RQCF_UPDATED);
Can this warn on every rt/dl -> ext deboost when WARN_DOUBLE_CLOCK is
enabled? For example, an ext task holding a PI futex that was boosted by a
SCHED_FIFO waiter and then unlocks:
mark_wakeup_next_waiter()
rt_mutex_adjust_prio()
rt_mutex_setprio()
update_rq_clock()
scx_prepare_task_sched_change()
update_rq_clock() <- WARN_ON_ONCE(RQCF_UPDATED)
This does not need CONFIG_SCHED_PROXY_EXEC, since without it
sched_proxy_block_task() is an empty stub and the clock update is all the
call does.
The comment on scx_prepare_task_sched_change() says the caller must pass
DEQUEUE_NOCLOCK so the rq clock is updated only once, and the commit message
calls the second update "harmless". scx_prepare_setscheduler(), whose caller
has already updated the rq clock, calls scx_block_proxy_donor() directly.
Would a variant without the clock update, or exposing scx_block_proxy_donor()
to core.c, avoid this?
Peter Zijlstra also replied to this patch on the list: "I can't understand
this. And I take a very dim view of sprinking magic hooks like this. So no."
He proposed instead having sched_class->switching_to() return a bool saying
whether the class accepts blocked tasks, with sched_change_end() blocking the
task. Andrea Righi agreed to take that approach over, noting that the block
must not dequeue a second time, donor and ctx->running must be reset, and
DEQUEUE_NOCLOCK must be dropped.
This patch still adds the explicit sched_ext specific call in
rt_mutex_setprio(). Is this approach still intended given that discussion?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/43353689014
prev parent reply other threads:[~2026-11-13 3:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 14:49 [PATCH 0/2] sched_ext: Fix entry-path contract breaks in core.c Tao Cui
2026-11-12 14:49 ` [PATCH 1/2] sched/core: Pass ENQUEUE_RQ_SELECTED on initial enqueue Tao Cui
2026-11-12 14:49 ` [PATCH 2/2] sched_ext: Block a retained donor before PI deboost routes it back to sched_ext Tao Cui
2026-11-12 15:21 ` Peter Zijlstra
2026-11-12 16:01 ` Peter Zijlstra
2026-11-12 16:32 ` Andrea Righi
2026-11-12 16:41 ` Peter Zijlstra
2026-11-12 16:50 ` Andrea Righi
2026-11-12 16:05 ` Andrea Righi
2026-11-12 16:31 ` Peter Zijlstra
2026-11-13 3:05 ` bot+bpf-ci [this message]
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=89f7ed00d7373ea7389e563810fbcd7ae775858e7fb592ad6e12cc1d1aee2565@mail.kernel.org \
--to=bot+bpf-ci@kernel.org \
--cc=andrii@kernel.org \
--cc=arighi@nvidia.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=changwoo@igalia.com \
--cc=cui.tao@linux.dev \
--cc=cuitao@kylinos.cn \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@kernel.org \
--cc=mason@kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=sched-ext@lists.linux.dev \
--cc=tj@kernel.org \
--cc=void@manifault.com \
--cc=yonghong.song@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®