| a9e3760b | 15-Sep-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Maintain an online cid mask in the scheduler arena
Schedulers on the default cid mapping treat [0, nr_online_cids) as the online set and restart on hotplug. Schedulers that install their
sched_ext: Maintain an online cid mask in the scheduler arena
Schedulers on the default cid mapping treat [0, nr_online_cids) as the online set and restart on hotplug. Schedulers that install their own mapping with scx_bpf_cid_override() have no way to learn which cids are online: the count no longer identifies members and the CPU-form cpumask is unusable from cid programs. This is an obvious hole in the cid API.
Add scx_bpf_online_cmask(), a kernel-maintained cmask in the scheduler's arena, allocated alongside the per-CPU scratch masks and populated after the cid mapping is finalized and before ops.init(), for child schedulers too. The pointer stays valid through ops.exit() with no reference to take. It is the arena offset as a void pointer, the same form struct_ops arena arguments arrive in. The verifier types the void return as a scalar for the program's arena cast.
The mask follows the SCX hotplug notifications: seeded from cpu_active_mask and updated before ops.cid_online/offline() runs, so it lags cpu_online_mask only inside a hotplug transition. Updates walk the scheduler list under the lock that also serializes unlinking. Reads are live, not atomic snapshots. Root initialization excludes hotplug.
v2: Reworded the getter kerneldoc (Andrea Righi).
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| 9e8581a0 | 18-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Sync common and compat headers from the scx repo
Sync common.bpf.h, compat.bpf.h and compat.h with the scx repo, which accumulated the following:
- __COMPAT_read_enum() can now recover 6
sched_ext: Sync common and compat headers from the scx repo
Sync common.bpf.h, compat.bpf.h and compat.h with the scx repo, which accumulated the following:
- __COMPAT_read_enum() can now recover 64-bit scx enum values from kernel BTF generated without BTF_KIND_ENUM64 support (pahole < 1.24 or --skip_encoding_btf_enum64, e.g. COS/GKE kernels), substituting values from the build-time vmlinux.h cross-checked against the low 32 bits the kernel does provide.
- is_migration_disabled() no longer assumes the BPF prolog always disables migration. Since 8e4f0b1ebcf2 ("bpf: use rcu_read_lock_dont_migrate() for trampoline.c") the prolog only does so under CONFIG_PREEMPT_RCU, so the old current-task test under-reported on v6.18+ !PREEMPT_RCU kernels. A runtime probe on bpf_scx_reg() handles older kernels with backported trampoline behavior.
- __COMPAT_scx_bpf_dsq_peek() is gated behind kernel v7.1 where 2f2ea7709266 ("sched_ext: Use dsq->first_task instead of list_empty() in dispatch_enqueue() FIFO-tail") fixed the kfunc spuriously returning NULL on non-empty FIFO DSQs, and the new scx_bpf_reenqueue_local_from_anywhere() provides a callable-from-anywhere reenqueue which prefers the generic scx_bpf_dsq_reenq(). Both were first posted by Gavin Guo and Changwoo Min and are picked up here with the review feedback folded in.
- __COMPAT_scx_bpf_cpu_curr() and the scx_bpf_cpu_rq() declaration are restored. Schedulers built from these headers still run on pre-v6.18 kernels where scx_bpf_cpu_curr() does not resolve and the scx_bpf_cpu_rq() fallback still exists.
- scx_clock_task() and scx_clock_pelt() document their stale-read behavior for remote idle CPUs under NO_HZ_IDLE.
Link: https://lore.kernel.org/all/20260817143126.562923-1-changwoo@igalia.com Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| e10b8b49 | 18-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Sync tools autogen enum headers from the scx repo
Regenerate enum_defs.autogen.h against the current tree, picking up the dispatch verdict enums and dropping the marker for the removed SC
sched_ext: Sync tools autogen enum headers from the scx repo
Regenerate enum_defs.autogen.h against the current tree, picking up the dispatch verdict enums and dropping the marker for the removed SCX_RQ_IN_BALANCE. Add enums_abi.autogen.h, a table of 64-bit scx enumerator values generated from vmlinux.h, used as the substitution source when the running kernel's BTF truncates 64-bit enum values to 32 bits.
Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| 56bbc912 | 11-Aug-2026 |
fangqiurong <fangqiurong@kylinos.cn> |
sched_ext: Fix scx_bpf_dsq_move_to_local___v2 compat detection
libbpf strips the last ___flavor suffix when resolving kfunc externs, so the bare ___v2 declaration resolves to scx_bpf_dsq_move_to_loc
sched_ext: Fix scx_bpf_dsq_move_to_local___v2 compat detection
libbpf strips the last ___flavor suffix when resolving kfunc externs, so the bare ___v2 declaration resolves to scx_bpf_dsq_move_to_local, whose BTF proto lacks @enq_flags. The extern never matches, bpf_ksym_exists() returns false on every kernel that has the ___v2 kfunc, and the macro falls back to ___v1, silently dropping @enq_flags.
Add the trailing ___compat suffix used by the other versioned externs in this file (scx_bpf_dsq_insert___v2, scx_bpf_reenqueue_local___v2).
Any caller passing non-zero @enq_flags through the compat macro silently loses them.
Fixes: 860683763ebf ("sched_ext: Add enq_flags to scx_bpf_dsq_move_to_local()") Cc: stable@vger.kernel.org # v7.1+ Assisted-by: Z.ai:glm-5.2 Signed-off-by: fangqiurong <fangqiurong@kylinos.cn> Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| 62f3d531 | 14-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Fix scx_bpf_dsq_reenq___compat kfunc extern prototype
scx_bpf_dsq_reenq() is registered with KF_IMPLICIT_ARGS and its kernel BTF prototype omits the trailing bpf_prog_aux argument. The __
sched_ext: Fix scx_bpf_dsq_reenq___compat kfunc extern prototype
scx_bpf_dsq_reenq() is registered with KF_IMPLICIT_ARGS and its kernel BTF prototype omits the trailing bpf_prog_aux argument. The ___compat extern declares the argument explicitly, so libbpf never matches the prototype and the weak extern silently stays unresolved on every kernel. The wrapper always takes the old fallback path, which disables generic reenq users like scx_qmap's lowpri mechanism and fails non-local reenq with "kernel too old" even on kernels that have the kfunc.
Drop the explicit aux argument. Also correct the stale v6.20 reference, the kfunc was added in v7.1.
Fixes: 9c34c5074d1b ("sched_ext: Introduce scx_bpf_dsq_reenq() for remote local DSQ reenqueue") Cc: stable@vger.kernel.org # v7.1+ Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| a05c5b5c | 12-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Convert scx_bpf_cid_override() to __arena array arguments
scx_bpf_cid_override() predates the cid-form arena transition and takes its arrays as verifier-checked mem+size buffers, forcing
sched_ext: Convert scx_bpf_cid_override() to __arena array arguments
scx_bpf_cid_override() predates the cid-form arena transition and takes its arrays as verifier-checked mem+size buffers, forcing scx_qmap to keep the cpu_to_cid and shard_start arrays in writable bss while the rest of its state lives in the arena. Unify on arena arguments before cid-form schedulers start seeing real use.
BPF now translates between BPF and kernel arena addresses for __arena arguments. Take the arrays as __arena arguments, with the counts passed in entries. The counts now size the snapshot copies and are bounds-checked before them.
scx_qmap moves the arrays into struct qmap_arena. As the arena is mmapped at load, the loader populates them between load and attach instead of before load.
The arena argument address translation is currently implemented only on x86-64. Schedulers calling this kfunc load only there for now.
Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| ffaab58d | 07-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Replace SCX_RQ_BAL_KEEP with a dispatch verdict return
SCX_RQ_BAL_KEEP tells the pick to keep running the previous task, a leftover from when balancing and picking were separate operation
sched_ext: Replace SCX_RQ_BAL_KEEP with a dispatch verdict return
SCX_RQ_BAL_KEEP tells the pick to keep running the previous task, a leftover from when balancing and picking were separate operations. An rq-level flag only works while dispatches and picks pair up one to one, which core scheduling breaks: selections interleave through dispatch's lock drops and a pick can consume a stale flag, keeping a task that has since been dequeued. Fixing core scheduling support requires the decision to travel with the dispatch that made it. Make scx_dispatch_sched() and balance_one() return an explicit verdict instead and drop the flag's plumbing from the tools autogen enum headers.
Also factor the pick-side invocation, its follow-up queueing and the post-dispatch checks out of do_pick_task_scx() into dispatch_pick(). No functional changes intended.
v2: Drop the SCX_RQ_BAL_KEEP plumbing from the tools autogen enum headers as well (Andrea).
Fixes: 4c95380701f5 ("sched/ext: Fold balance_scx() into pick_task_scx()") Cc: stable@vger.kernel.org # v6.19+ Signed-off-by: Tejun Heo <tj@kernel.org>
show more ...
|
| 1f15b9a9 | 03-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Sync tools autogen enum headers
Mechanical regeneration for the enumerators added by the slice write rework and the rescue machinery. BPF schedulers reference SCX_ENQ_RESCUE, the rest are
sched_ext: Sync tools autogen enum headers
Mechanical regeneration for the enumerators added by the slice write rework and the rescue machinery. BPF schedulers reference SCX_ENQ_RESCUE, the rest are enum_defs presence markers.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| 5fd50174 | 03-Aug-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Add bandwidth-limited rescue execution for stranded tasks
A local DSQ insert lacking the needed caps is diverted to the reject DSQ and bounced back through ops.enqueue() so the scheduler
sched_ext: Add bandwidth-limited rescue execution for stranded tasks
A local DSQ insert lacking the needed caps is diverted to the reject DSQ and bounced back through ops.enqueue() so the scheduler can re-decide. That recovery assumes the scheduler has somewhere legal to send the task. When it doesn't, e.g. when the task's affinity is restricted to cids delegated away, the task starves until the stall watchdog ejects the scheduler. An exiting task is worse - it skips ops.enqueue() and the rejection becomes a self-requeuing cycle that burns the CPU until the watchdog fires.
Add SCX_ENQ_RESCUE, a fallback modifier on local DSQ inserts. When the insert would be rejected for missing caps, the kernel takes over and runs the task on the target CPU without consulting the owning scheduler. The kernel sets the flag itself when enqueueing an exiting task.
Rescue is a last-resort forward-progress backstop with a persistent disadvantage, not a way around cap enforcement. A per-CPU token bucket accrues rescue_bandwidth_ppt (default 2%) of CPU time and rescues run one at a time in arrival order. Each is granted a slice of the rescue_quantum_us (default 5ms) quantum divided across the waiters, waits at the tail of the local DSQ claiming no priority, and rejoins its scheduler as a fresh arrival once the slice is served.
The schedulers keep their normal control over an admitted rescuee and may preempt or reslice it. Service is measured on CPU time actually received, so neither shortens the rescue. Prolonged denial escalates - the remaining slice turns into protected execution (SCX_TASK_PROTECTED) and the rescuee preempts the current task. Escalation is paced by the same bucket, and delivered service converges on the configured bandwidth no matter how aggressively the schedulers dispatch.
Both knobs are root-only and SCX_RESCUE_DISABLE turns rescue off, making SCX_ENQ_RESCUE inserts reject as usual.
v2: - Add SCX_OPS_OPEN() fix-ups for the new ops fields so cpu-form schedulers setting them still load on older kernels. (Andrea)
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| 3a21e34e | 24-Jul-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Gate scx_bpf_cidperf_set() behind a new SCX_CAP_PERF
scx_bpf_cidperf_set() reaches cpufreq with no cap check, so any cid-form sub-sched can steer the frequency of any cid in its view, inc
sched_ext: Gate scx_bpf_cidperf_set() behind a new SCX_CAP_PERF
scx_bpf_cidperf_set() reaches cpufreq with no cap check, so any cid-form sub-sched can steer the frequency of any cid in its view, including ones it holds nothing on.
Gate it behind a new SCX_CAP_PERF rather than SCX_CAP_BASE: hardware control is a separate axis from queue access - a parent may well delegate scheduling on a cid without handing over its frequency. PERF neither implies nor is implied by the other caps. The check runs under the target rq's lock, which ecaps updates are also folded under, so it is authoritative - a write can never land after a revoke has taken effect. Denials are counted in SCX_EV_SUB_CIDPERF_DENIED.
The operation is synchronous and the outcome is reported to the caller: scx_bpf_cidperf_set() now returns 0 or -errno, -EACCES on denial. The cid-form interface is still under initial development, so the signature is changed in place without versioning.
scx_qmap grants PERF alongside its existing cid grants so the cpuperf demo keeps working in sub-scheds.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| d327796b | 18-Jul-2026 |
Tejun Heo <tj@kernel.org> |
tools/sched_ext: Add SCX_OPS_CID_OPEN for cid-form schedulers
SCX_OPS_OPEN() clears compat-gated ops fields which the running kernel lacks. The clears dereference cpu-form member names and compile f
tools/sched_ext: Add SCX_OPS_CID_OPEN for cid-form schedulers
SCX_OPS_OPEN() clears compat-gated ops fields which the running kernel lacks. The clears dereference cpu-form member names and compile for cid-form skeletons only because both ops structs currently name their cgroup ops identically, which an upcoming rename will end. No load-time fix-up can apply to a cid-form scheduler anyway as the cid form postdates every compat-gated op.
Factor the skeleton open path out of SCX_OPS_OPEN() and add SCX_OPS_CID_OPEN() which uses only that shared part. Switch scx_qmap, the only cid-form scheduler, over.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| e051308b | 14-Jul-2026 |
Tejun Heo <tj@kernel.org> |
tools/sched_ext: Add three-mask cmask intersection iterator
Add cmask_next_and2_set() and its round-robin wrap, extending cmask_next_and_set() to a three-mask intersection: the next cid set in all t
tools/sched_ext: Add three-mask cmask intersection iterator
Add cmask_next_and2_set() and its round-robin wrap, extending cmask_next_and_set() to a three-mask intersection: the next cid set in all three masks at or after @start. A caller iterating the intersection of three cmasks can then scan it in one pass, folding the third mask into the word-level AND rather than skipping non-members one candidate at a time.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| b0a2ca6a | 14-Jul-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Add scx_bpf_sub_kill() to evict a child sub-scheduler
A cid-form scheduler can grant caps to and revoke them from its child sub-schedulers but has no way to tear one down. Add scx_bpf_sub
sched_ext: Add scx_bpf_sub_kill() to evict a child sub-scheduler
A cid-form scheduler can grant caps to and revoke them from its child sub-schedulers but has no way to tear one down. Add scx_bpf_sub_kill() to evict a direct child with a printf-style reason that reaches the child's scx_exit_info. No exit code is taken because the child is a separate scheduler whose exit-code semantics the parent cannot know. The child and its subtree are disabled through the usual async path under a new exit kind, SCX_EXIT_PARENT_KILL.
The bstr formatting infrastructure in ext.c is exposed through internal.h with scx_ prefixes so the kfunc, which lives in sub.c, can format the reason.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| 86094b95 | 14-Jul-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Add per-shard cap delegation for sub-schedulers
Caps are per-cid permissions parents delegate to direct children via scx_bpf_sub_grant() / scx_bpf_sub_revoke(). A child's cap set is alway
sched_ext: Add per-shard cap delegation for sub-schedulers
Caps are per-cid permissions parents delegate to direct children via scx_bpf_sub_grant() / scx_bpf_sub_revoke(). A child's cap set is always a subset of its parent's. Sub-scheds check their caps locally, and cross-sched communication is needed only when the delegation set itself changes.
Caps will be used to implement sub-sched scheduling on the enqueue path. Picking a cid for a task at a leaf depends on which cids the leaf is allowed to use, and resolving that programmatically on every enqueue would mean a cross-sched round-trip call chain, possibly retrying if the request can't be granted as-is. The dispatch path is different - it runs as top-down recursion via scx_bpf_sub_dispatch().
Locking is per shard. cid space is split into shards, and each sub-sched has its own pshard->lock for each shard. Operations are broken up on shard boundaries. Different shards never contend. Shards are expected to be topology-aligned and likely to serve as the locality unit when cids are allocated to schedulers, so per-shard lock granularity scales naturally with the allocation pattern.
This patch adds the framework with a single dummy cap. Real caps land in later patches.
The enable path is reordered for pshards. scx_arena_pool_init() moves ahead of scx_link_sched() so the pshards are allocated before the sched becomes reachable - scx_alloc_pshards() skips allocation when the arena pool isn't initialized.
- scx_bpf_sub_grant(): Per-cid all-or-nothing grant to direct child. - scx_bpf_sub_revoke(): Clear caps on @cmask across @child and its subtree. - scx_bpf_sub_caps(): Lockless snapshot of caps on a cid range.
/sys/kernel/sched_ext/SCHED/caps shows the caps each scheduler currently holds.
v4: Move the pshard[] full build/publish and the err_disable scx_error() recording to earlier patches. (sashiko AI) v3: Build pshard[] fully before publishing it, read it with READ_ONCE. (sashiko AI) v2: Validate ops before scx_link_sched() publishes the sub. (sashiko AI)
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| 30067643 | 14-Jul-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Add shard boundaries to scx_bpf_cid_override()
An overridden cid mapping invalidates the auto-generated shard layout, so the override call has to provide both. Extend scx_bpf_cid_override
sched_ext: Add shard boundaries to scx_bpf_cid_override()
An overridden cid mapping invalidates the auto-generated shard layout, so the override call has to provide both. Extend scx_bpf_cid_override() with a shard_start[] array that lists the first cid of each shard (starting at 0, strictly increasing, last shard implicitly extends to num_possible_cpus()).
A scheduler that wants only custom shards with the auto-generated cid mapping can read the current mapping and pass it back unchanged.
Overridden shards can span NUMA nodes, so scx_shard_node[] is rebuilt by majority count: each shard is assigned to the node that owns the most cpus in it.
v2: Snapshot the caller's cpu_to_cid/shard_start arrays before validating. (sashiko AI)
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|
| b38332be | 10-Jul-2026 |
Tejun Heo <tj@kernel.org> |
sched_ext: Make scx_bpf_kick_cid() return void
scx_bpf_kick_cid() returned an error code, but the value conveys nothing actionable and no caller consumes it. The kick is asynchronous, so a successfu
sched_ext: Make scx_bpf_kick_cid() return void
scx_bpf_kick_cid() returned an error code, but the value conveys nothing actionable and no caller consumes it. The kick is asynchronous, so a successful return only means it was queued. An invalid @cid is already reported through scx_error() by scx_cid_to_cpu(), and a missing scheduler leaves nothing to kick.
Make scx_bpf_kick_cid() return void to match scx_bpf_kick_cpu(). The cid-form kfuncs are not in practical use yet, so the ABI change is safe.
Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
show more ...
|