From: Andrea Righi <arighi@nvidia.com>
To: Hui Su <sh_def@163.com>
Cc: tj@kernel.org, void@manifault.com, changwoo@igalia.com,
mingo@redhat.com, peterz@infradead.org, juri.lelli@redhat.com,
vincent.guittot@linaro.org, dietmar.eggemann@arm.com,
rostedt@goodmis.org, bsegall@google.com, mgorman@suse.de,
vschneid@redhat.com, kprateek.nayak@amd.com,
sched-ext@lists.linux.dev, linux-kernel@vger.kernel.org,
bpf@vger.kernel.org, stable@vger.kernel.org
Subject: Re: [PATCH v2] sched_ext: idle: Respect task affinity in restricted CPU selection
Date: Sun, 11 Oct 2026 16:39:13 +0200 [thread overview]
Message-ID: <asufkdwCQvilJEqr@gpd4> (raw)
In-Reply-To: <20261011131700.1351541-1-sh_def@163.com>
Hi Hui,
On Sun, Oct 11, 2026 at 10:17:00PM +0900, Hui Su wrote:
> The restricted select_cpu kfunc path handles single-CPU and
> migration-disabled tasks without going through scx_select_cpu_dfl().
>
> It currently uses prev_cpu as the candidate. However, prev_cpu is only a
> hint and may no longer be usable after an affinity change. When the caller
> supplies @allowed, the restricted path can also claim and return an idle
> CPU which isn't in p->cpus_ptr.
>
> Derive the candidate from task state instead. Use the sole CPU in
> p->cpus_ptr for single-CPU tasks and task_cpu(p) for migration-disabled
> tasks. Validate the candidate against the task's effective affinity and
> the caller-provided mask before claiming its idle state.
>
> The validation must happen before scx_idle_test_and_clear_cpu(), as a
> successful call consumes the CPU's idle bit. A later placement validation
> therefore cannot undo the idle-state side effect.
>
> Single-CPU and migration-disabled tasks skip ops.select_cpu(), so this
> path can instead be reached when the CPU-selection kfunc is called from
> other contexts such as ops.enqueue(). The normal ops.select_cpu() path is
> unchanged.
>
> Fixes: 683d2d0faba1 ("sched_ext: idle: Introduce scx_bpf_select_cpu_and()")
> Cc: stable@vger.kernel.org
> Signed-off-by: Hui Su <sh_def@163.com>
> ---
> Testing:
> - x86_64 KVM/QEMU private BPF test-run harness:
> - The baseline returned CPU1 outside the task affinity; v2 returned
> -EBUSY.
> - With a stale prev_cpu, the baseline returned -EBUSY; v2 selected the
> task's idle CPU0.
> - A caller mask excluding the task's candidate CPU returned -EBUSY with v2.
> - The stock sched_ext allowed_cpus selftest passed.
> - Built vmlinux and bzImage with CONFIG_PREEMPT_RCU=y.
> - Built kernel/sched/build_policy.o with CONFIG_PREEMPT_RCU=n and CONFIG_SMP=n.
>
> Changes in v2:
> - Derive the restricted-path candidate from task state instead of prev_cpu.
> - Document the idle-bit side effect and the ops.enqueue() reachability.
>
> v1: https://lore.kernel.org/lkml/20261011025256.4180374-1-sh_def@163.com/
> ---
> kernel/sched/ext/idle.c | 20 ++++++++++++++------
> 1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/kernel/sched/ext/idle.c b/kernel/sched/ext/idle.c
> index aa9fb6de0ad6..1ccea60e9012 100644
> --- a/kernel/sched/ext/idle.c
> +++ b/kernel/sched/ext/idle.c
> @@ -958,6 +958,7 @@ static s32 select_cpu_from_kfunc(struct scx_sched *sch, struct task_struct *p,
> {
> unsigned long irq_flags;
> bool we_locked = false;
> + bool migration_disabled;
> s32 cpu;
>
> if (!scx_cpu_valid(sch, prev_cpu, NULL))
> @@ -995,14 +996,21 @@ static s32 select_cpu_from_kfunc(struct scx_sched *sch, struct task_struct *p,
> /*
> * This may also be called from ops.enqueue(), so we need to handle
> * per-CPU tasks as well. For these tasks, we can skip all idle CPU
> - * selection optimizations and simply check whether the previously
> - * used CPU is idle and within the allowed cpumask.
> + * selection optimizations and simply check whether the task's only
> + * usable CPU is idle and within the allowed cpumask.
> */
> - if (p->nr_cpus_allowed == 1 || is_bpf_migration_disabled(p)) {
> - if (cpumask_test_cpu(prev_cpu, allowed ?: p->cpus_ptr) &&
> - scx_idle_test_and_clear_cpu(prev_cpu))
> - cpu = prev_cpu;
> + migration_disabled = is_bpf_migration_disabled(p);
> +
> + if (p->nr_cpus_allowed == 1 || migration_disabled) {
> + if (migration_disabled)
> + cpu = task_cpu(p);
> else
> + cpu = cpumask_first(p->cpus_ptr);
> +
> + if ((migration_disabled &&
> + !cpumask_test_cpu(cpu, p->cpus_ptr)) ||
> + (allowed && !cpumask_test_cpu(cpu, allowed)) ||
> + !scx_idle_test_and_clear_cpu(cpu))
> cpu = -EBUSY;
Sorry, I suggested this, but I just realized that we break SCX_PICK_IDLE_IN_NODE
if we do this. What if we factor the check with an helper? Something like this:
static s32 select_cpu_restricted(struct task_struct *p, s32 prev_cpu,
const struct cpumask *allowed, u64 flags,
bool migration_disabled)
{
s32 cpu;
if (migration_disabled)
cpu = task_cpu(p);
else
cpu = cpumask_first(p->cpus_ptr);
if (!cpumask_test_cpu(cpu, p->cpus_ptr))
return -EBUSY;
if (allowed && !cpumask_test_cpu(cpu, allowed))
return -EBUSY;
if (flags & SCX_PICK_IDLE_IN_NODE) {
int node = scx_cpu_node_if_enabled(prev_cpu);
if (scx_cpu_node_if_enabled(cpu) != node)
return -EBUSY;
}
if (!scx_idle_test_and_clear_cpu(cpu))
return -EBUSY;
return cpu;
}
Then the caller becomes:
migration_disabled = is_bpf_migration_disabled(p);
if (p->nr_cpus_allowed == 1 || migration_disabled)
cpu = select_cpu_restricted(p, prev_cpu, allowed, flags, migration_disabled);
else
cpu = scx_select_cpu_dfl(p, prev_cpu, wake_flags, allowed ?: p->cpus_ptr, flags);
Thanks,
-Andrea
next prev parent reply other threads:[~2026-10-11 14:39 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-11 2:52 [PATCH] sched_ext: idle: Respect task affinity in restricted CPU selection Hui Su
2026-10-11 7:02 ` Andrea Righi
2026-10-11 9:10 ` Hui Su
2026-10-11 13:17 ` [PATCH v2] " Hui Su
2026-10-11 14:39 ` Andrea Righi [this message]
2026-10-11 17:09 ` Hui Su
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=asufkdwCQvilJEqr@gpd4 \
--to=arighi@nvidia.com \
--cc=bpf@vger.kernel.org \
--cc=bsegall@google.com \
--cc=changwoo@igalia.com \
--cc=dietmar.eggemann@arm.com \
--cc=juri.lelli@redhat.com \
--cc=kprateek.nayak@amd.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mgorman@suse.de \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=sched-ext@lists.linux.dev \
--cc=sh_def@163.com \
--cc=stable@vger.kernel.org \
--cc=tj@kernel.org \
--cc=vincent.guittot@linaro.org \
--cc=void@manifault.com \
--cc=vschneid@redhat.com \
/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.