* [PATCH 1/4] sched_ext: Order single-cid cmask helpers as (cid, mask)
2026-06-04 2:00 [PATCHSET v2 sched_ext/for-7.2] sched_ext: cid/cmask interface prep Tejun Heo
@ 2026-06-04 2:00 ` Tejun Heo
2026-06-04 2:00 ` [PATCH 2/4] tools/sched_ext: " Tejun Heo
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2026-06-04 2:00 UTC (permalink / raw)
To: David Vernet, Andrea Righi, Changwoo Min
Cc: Emil Tsalapatis, sched-ext, linux-kernel, Tejun Heo
__scx_cmask_set(), __scx_cmask_contains() and __scx_cmask_word() take the
cmask first and the cid second. The kernel's bit and cpumask predicates put
the index first: test_bit(nr, addr), cpumask_test_cpu(cpu, mask). Reorder
the cmask helpers to (cid, mask) for consistency, ahead of new single-cid
ops added next. Mask-level ops (and/or/andnot/copy/subset/intersects) keep
(dst, src).
Signed-off-by: Tejun Heo <tj@kernel.org>
---
kernel/sched/ext_cid.c | 2 +-
kernel/sched/ext_cid.h | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/kernel/sched/ext_cid.c b/kernel/sched/ext_cid.c
index 808c6390da5a..66944a7ef79d 100644
--- a/kernel/sched/ext_cid.c
+++ b/kernel/sched/ext_cid.c
@@ -267,7 +267,7 @@ void scx_cpumask_to_cmask(const struct cpumask *src, struct scx_cmask *dst)
s32 cid = __scx_cpu_to_cid(cpu);
if (cid >= 0)
- __scx_cmask_set(dst, cid);
+ __scx_cmask_set(cid, dst);
}
}
diff --git a/kernel/sched/ext_cid.h b/kernel/sched/ext_cid.h
index abea22ba2cc2..46fd8eda0443 100644
--- a/kernel/sched/ext_cid.h
+++ b/kernel/sched/ext_cid.h
@@ -147,13 +147,13 @@ static inline bool scx_is_cid_type(void)
return static_branch_unlikely(&__scx_is_cid_type);
}
-static inline bool __scx_cmask_contains(const struct scx_cmask *m, u32 cid)
+static inline bool __scx_cmask_contains(u32 cid, const struct scx_cmask *m)
{
return likely(cid >= m->base && cid < m->base + m->nr_cids);
}
/* Word in bits[] covering @cid. @cid must satisfy __scx_cmask_contains(). */
-static inline u64 *__scx_cmask_word(const struct scx_cmask *m, u32 cid)
+static inline u64 *__scx_cmask_word(u32 cid, const struct scx_cmask *m)
{
return (u64 *)&m->bits[cid / 64 - m->base / 64];
}
@@ -218,11 +218,11 @@ static inline void scx_cmask_reframe(struct scx_cmask *m, u32 base, u32 nr_cids)
m->nr_cids = nr_cids;
}
-static inline void __scx_cmask_set(struct scx_cmask *m, u32 cid)
+static inline void __scx_cmask_set(u32 cid, struct scx_cmask *m)
{
- if (!__scx_cmask_contains(m, cid))
+ if (!__scx_cmask_contains(cid, m))
return;
- *__scx_cmask_word(m, cid) |= BIT_U64(cid & 63);
+ *__scx_cmask_word(cid, m) |= BIT_U64(cid & 63);
}
#endif /* _KERNEL_SCHED_EXT_CID_H */
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/4] tools/sched_ext: Order single-cid cmask helpers as (cid, mask)
2026-06-04 2:00 [PATCHSET v2 sched_ext/for-7.2] sched_ext: cid/cmask interface prep Tejun Heo
2026-06-04 2:00 ` [PATCH 1/4] sched_ext: Order single-cid cmask helpers as (cid, mask) Tejun Heo
@ 2026-06-04 2:00 ` Tejun Heo
2026-06-04 2:00 ` [PATCH 3/4] sched_ext: Add scx_cmask_test() and scx_cmask_for_each_cid() Tejun Heo
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2026-06-04 2:00 UTC (permalink / raw)
To: David Vernet, Andrea Righi, Changwoo Min
Cc: Emil Tsalapatis, sched-ext, linux-kernel, Tejun Heo
The BPF arena single-cid cmask helpers take the cmask first and the cid
second. Reorder them to (cid, mask) to match the kernel-side helpers and
the test_bit(nr, addr), cpumask_test_cpu(cpu, mask) convention. Range and
iteration helpers keep (mask, start).
Signed-off-by: Tejun Heo <tj@kernel.org>
---
tools/sched_ext/include/scx/cid.bpf.h | 60 +++++++++++++--------------
tools/sched_ext/scx_qmap.bpf.c | 12 +++---
2 files changed, 36 insertions(+), 36 deletions(-)
diff --git a/tools/sched_ext/include/scx/cid.bpf.h b/tools/sched_ext/include/scx/cid.bpf.h
index 70f2a3829af4..9d89bb57e201 100644
--- a/tools/sched_ext/include/scx/cid.bpf.h
+++ b/tools/sched_ext/include/scx/cid.bpf.h
@@ -40,12 +40,12 @@
*/
#define CMASK_NR_WORDS(nr_cids) ((u32)(((u64)(nr_cids) + 63) / 64 + 1))
-static __always_inline bool __cmask_contains(const struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool __cmask_contains(u32 cid, const struct scx_cmask __arena *m)
{
return cid >= m->base && cid < m->base + m->nr_cids;
}
-static __always_inline u64 __arena *__cmask_word(const struct scx_cmask __arena *m, u32 cid)
+static __always_inline u64 __arena *__cmask_word(u32 cid, const struct scx_cmask __arena *m)
{
return (u64 __arena *)&m->bits[cid / 64 - m->base / 64];
}
@@ -122,11 +122,11 @@ static __always_inline void cmask_reframe(struct scx_cmask __arena *m, u32 base,
m->nr_cids = nr_cids;
}
-static __always_inline bool cmask_test(const struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool cmask_test(u32 cid, const struct scx_cmask __arena *m)
{
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return false;
- return *__cmask_word(m, cid) & BIT_U64(cid & 63);
+ return *__cmask_word(cid, m) & BIT_U64(cid & 63);
}
/*
@@ -140,15 +140,15 @@ static __always_inline bool cmask_test(const struct scx_cmask __arena *m, u32 ci
*/
#define CMASK_CAS_TRIES (1U << 23)
-static __always_inline void cmask_set(struct scx_cmask __arena *m, u32 cid)
+static __always_inline void cmask_set(u32 cid, struct scx_cmask __arena *m)
{
u64 __arena *w;
u64 bit, old, new;
u32 i;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
bit = BIT_U64(cid & 63);
bpf_for(i, 0, CMASK_CAS_TRIES) {
old = *w;
@@ -161,15 +161,15 @@ static __always_inline void cmask_set(struct scx_cmask __arena *m, u32 cid)
scx_bpf_error("cmask_set CAS exhausted at cid %u", cid);
}
-static __always_inline void cmask_clear(struct scx_cmask __arena *m, u32 cid)
+static __always_inline void cmask_clear(u32 cid, struct scx_cmask __arena *m)
{
u64 __arena *w;
u64 bit, old, new;
u32 i;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
bit = BIT_U64(cid & 63);
bpf_for(i, 0, CMASK_CAS_TRIES) {
old = *w;
@@ -182,15 +182,15 @@ static __always_inline void cmask_clear(struct scx_cmask __arena *m, u32 cid)
scx_bpf_error("cmask_clear CAS exhausted at cid %u", cid);
}
-static __always_inline bool cmask_test_and_set(struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool cmask_test_and_set(u32 cid, struct scx_cmask __arena *m)
{
u64 __arena *w;
u64 bit, old, new;
u32 i;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return false;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
bit = BIT_U64(cid & 63);
bpf_for(i, 0, CMASK_CAS_TRIES) {
old = *w;
@@ -204,15 +204,15 @@ static __always_inline bool cmask_test_and_set(struct scx_cmask __arena *m, u32
return false;
}
-static __always_inline bool cmask_test_and_clear(struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool cmask_test_and_clear(u32 cid, struct scx_cmask __arena *m)
{
u64 __arena *w;
u64 bit, old, new;
u32 i;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return false;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
bit = BIT_U64(cid & 63);
bpf_for(i, 0, CMASK_CAS_TRIES) {
old = *w;
@@ -226,43 +226,43 @@ static __always_inline bool cmask_test_and_clear(struct scx_cmask __arena *m, u3
return false;
}
-static __always_inline void __cmask_set(struct scx_cmask __arena *m, u32 cid)
+static __always_inline void __cmask_set(u32 cid, struct scx_cmask __arena *m)
{
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return;
- *__cmask_word(m, cid) |= BIT_U64(cid & 63);
+ *__cmask_word(cid, m) |= BIT_U64(cid & 63);
}
-static __always_inline void __cmask_clear(struct scx_cmask __arena *m, u32 cid)
+static __always_inline void __cmask_clear(u32 cid, struct scx_cmask __arena *m)
{
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return;
- *__cmask_word(m, cid) &= ~BIT_U64(cid & 63);
+ *__cmask_word(cid, m) &= ~BIT_U64(cid & 63);
}
-static __always_inline bool __cmask_test_and_set(struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool __cmask_test_and_set(u32 cid, struct scx_cmask __arena *m)
{
u64 bit = BIT_U64(cid & 63);
u64 __arena *w;
u64 prev;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return false;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
prev = *w & bit;
*w |= bit;
return prev;
}
-static __always_inline bool __cmask_test_and_clear(struct scx_cmask __arena *m, u32 cid)
+static __always_inline bool __cmask_test_and_clear(u32 cid, struct scx_cmask __arena *m)
{
u64 bit = BIT_U64(cid & 63);
u64 __arena *w;
u64 prev;
- if (!__cmask_contains(m, cid))
+ if (!__cmask_contains(cid, m))
return false;
- w = __cmask_word(m, cid);
+ w = __cmask_word(cid, m);
prev = *w & bit;
*w &= ~bit;
return prev;
@@ -671,7 +671,7 @@ static __always_inline void cmask_from_cpumask(struct scx_cmask __arena *m,
continue;
cid = scx_bpf_cpu_to_cid(cpu);
if (cid >= 0)
- __cmask_set(m, cid);
+ __cmask_set(cid, m);
}
}
diff --git a/tools/sched_ext/scx_qmap.bpf.c b/tools/sched_ext/scx_qmap.bpf.c
index 8a2d6a8ebd8e..fd9a82a67627 100644
--- a/tools/sched_ext/scx_qmap.bpf.c
+++ b/tools/sched_ext/scx_qmap.bpf.c
@@ -214,7 +214,7 @@ static s32 pick_direct_dispatch_cid(struct task_struct *p, s32 prev_cid,
if (!always_enq_immed && p->nr_cpus_allowed == 1)
return prev_cid;
- if (cmask_test_and_clear(qa_idle_cids, prev_cid))
+ if (cmask_test_and_clear(prev_cid, qa_idle_cids))
return prev_cid;
cid = prev_cid;
@@ -224,7 +224,7 @@ static s32 pick_direct_dispatch_cid(struct task_struct *p, s32 prev_cid,
barrier_var(cid);
if (cid >= nr_cids)
return -1;
- if (cmask_test_and_clear(qa_idle_cids, cid))
+ if (cmask_test_and_clear(cid, qa_idle_cids))
return cid;
}
return -1;
@@ -534,7 +534,7 @@ static bool dispatch_highpri(bool from_timer)
if (!(taskc = lookup_task_ctx(p)))
return false;
- if (cmask_test(&taskc->cpus_allowed, this_cid))
+ if (cmask_test(this_cid, &taskc->cpus_allowed))
cid = this_cid;
else
cid = cmask_next_set_wrap(&taskc->cpus_allowed,
@@ -656,7 +656,7 @@ void BPF_STRUCT_OPS(qmap_dispatch, s32 cid, struct task_struct *prev)
* document this class of issue -- other schedulers
* seeing similar warnings can use this as a reference.
*/
- if (!cmask_test(&taskc->cpus_allowed, cid))
+ if (!cmask_test(cid, &taskc->cpus_allowed))
scx_bpf_kick_cid(scx_bpf_task_cid(p), 0);
batch--;
@@ -913,9 +913,9 @@ void BPF_STRUCT_OPS(qmap_update_idle, s32 cid, bool idle)
{
QMAP_TOUCH_ARENA();
if (idle)
- cmask_set(qa_idle_cids, cid);
+ cmask_set(cid, qa_idle_cids);
else
- cmask_clear(qa_idle_cids, cid);
+ cmask_clear(cid, qa_idle_cids);
}
void BPF_STRUCT_OPS(qmap_set_cmask, struct task_struct *p,
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 4/4] sched_ext: Make scx_bpf_kick_cid() return s32
2026-06-04 2:00 [PATCHSET v2 sched_ext/for-7.2] sched_ext: cid/cmask interface prep Tejun Heo
` (2 preceding siblings ...)
2026-06-04 2:00 ` [PATCH 3/4] sched_ext: Add scx_cmask_test() and scx_cmask_for_each_cid() Tejun Heo
@ 2026-06-04 2:00 ` Tejun Heo
2026-06-04 6:18 ` [PATCHSET v2 sched_ext/for-7.2] sched_ext: cid/cmask interface prep Andrea Righi
2026-06-04 8:32 ` Tejun Heo
5 siblings, 0 replies; 8+ messages in thread
From: Tejun Heo @ 2026-06-04 2:00 UTC (permalink / raw)
To: David Vernet, Andrea Righi, Changwoo Min
Cc: Emil Tsalapatis, sched-ext, linux-kernel, Tejun Heo
Switch scx_bpf_kick_cid() from void to s32 so future cap enforcement can
surface failures. cid interface is introduced in this cycle and has no
external users, so the ABI change is safe. Subsequent patches will add
-EPERM returns when the calling sub-sched lacks the required cap on the
target cid.
v2: Return scx_cid_to_cpu()'s errno instead of -EINVAL. (Andrea)
Signed-off-by: Tejun Heo <tj@kernel.org>
---
kernel/sched/ext.c | 13 ++++++++-----
tools/sched_ext/include/scx/common.bpf.h | 2 +-
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 32ebbc351564..62769abb553a 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -9405,9 +9405,10 @@ __bpf_kfunc void scx_bpf_kick_cpu(s32 cpu, u64 flags, const struct bpf_prog_aux
* @flags: %SCX_KICK_* flags
* @aux: implicit BPF argument to access bpf_prog_aux hidden from BPF progs
*
- * cid-addressed equivalent of scx_bpf_kick_cpu().
+ * cid-addressed equivalent of scx_bpf_kick_cpu(). Return 0 on success,
+ * -errno otherwise.
*/
-__bpf_kfunc void scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux *aux)
+__bpf_kfunc s32 scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux *aux)
{
struct scx_sched *sch;
s32 cpu;
@@ -9415,10 +9416,12 @@ __bpf_kfunc void scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux
guard(rcu)();
sch = scx_prog_sched(aux);
if (unlikely(!sch))
- return;
+ return -ENODEV;
cpu = scx_cid_to_cpu(sch, cid);
- if (cpu >= 0)
- scx_kick_cpu(sch, cpu, flags);
+ if (cpu < 0)
+ return cpu;
+ scx_kick_cpu(sch, cpu, flags);
+ return 0;
}
/**
diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
index 5f715d69cde6..9591a6e778ce 100644
--- a/tools/sched_ext/include/scx/common.bpf.h
+++ b/tools/sched_ext/include/scx/common.bpf.h
@@ -105,7 +105,7 @@ void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __
s32 scx_bpf_cpu_to_cid(s32 cpu) __ksym __weak;
s32 scx_bpf_cid_to_cpu(s32 cid) __ksym __weak;
void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out) __ksym __weak;
-void scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak;
+s32 scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak;
s32 scx_bpf_task_cid(const struct task_struct *p) __ksym __weak;
s32 scx_bpf_this_cid(void) __ksym __weak;
struct task_struct *scx_bpf_cid_curr(s32 cid) __ksym __weak;
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread