STRUCT SCHED_EXT_OPS_CID(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸ’… struct sched_ext_ops_cid(9) β€” like, the cid-flavored twin of struct sched_ext_ops

okay so real talk, bestie: you're in the Kernel API Manual, section 9, and this page is all about struct sched_ext_ops_cid β€” the cid-form alternative to struct sched_ext_ops. it's giving "same energy, different vocabulary" and honestly? iconic. ✨


🌸 NAME 🌸

struct sched_ext_ops_cid β€” the cid-form alternative to struct sched_ext_ops. no cap, that's literally the whole name. πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

struct sched_ext_ops_cid {
    s32 (*select_cid)(struct task_struct *p, s32 prev_cid, u64 wake_flags);
    void (*enqueue)(struct task_struct *p, u64 enq_flags);
    void (*dequeue)(struct task_struct *p, u64 deq_flags);
    void (*dispatch)(s32 cid, struct task_struct *prev);
    void (*tick)(struct task_struct *p);
    void (*runnable)(struct task_struct *p, u64 enq_flags);
    void (*running)(struct task_struct *p);
    void (*stopping)(struct task_struct *p, bool runnable);
    void (*quiescent)(struct task_struct *p, u64 deq_flags);
    bool (*yield)(struct task_struct *from, struct task_struct *to);
    bool (*core_sched_before)(struct task_struct *a, struct task_struct *b);
    void (*set_weight)(struct task_struct *p, u32 weight);
    void (*set_cmask)(struct task_struct *p, const struct scx_cmask *cmask__arena);
    void (*update_idle)(s32 cid, bool idle);
    s32 (*init_task)(struct task_struct *p, struct scx_init_task_args *args);
    void (*exit_task)(struct task_struct *p, struct scx_exit_task_args *args);
    void (*enable)(struct task_struct *p, struct scx_enable_args *args);
    void (*disable)(struct task_struct *p);
    void (*dump)(struct scx_dump_ctx *ctx);
    void (*dump_cid)(struct scx_dump_ctx *ctx, s32 cid, bool idle);
    void (*dump_task)(struct scx_dump_ctx *ctx, struct task_struct *p);
  #ifdef CONFIG_EXT_GROUP_SCHED;
    s32 (*cpuctl_init)(struct cgroup *cgrp, struct scx_cgroup_init_args *args);
    void (*cpuctl_exit)(struct cgroup *cgrp);
    s32 (*cpuctl_prep_move)(struct task_struct *p, struct cgroup *from, struct cgroup *to);
    void (*cpuctl_move)(struct task_struct *p, struct cgroup *from, struct cgroup *to);
    void (*cpuctl_cancel_move)(struct task_struct *p, struct cgroup *from, struct cgroup *to);
    void (*cpuctl_set_weight)(struct cgroup *cgrp, u32 weight);
    void (*cpuctl_set_bandwidth)(struct cgroup *cgrp, u64 period_us, u64 quota_us, u64 burst_us);
    void (*cpuctl_set_idle)(struct cgroup *cgrp, bool idle);
  #endif ;
    s32 (*sub_attach)(struct scx_sub_attach_args *args);
    void (*sub_detach)(struct scx_sub_detach_args *args);
    void (*sub_caps_updated)(const struct scx_cmask *cmask__arena, u64 caps);
    void (*sub_ecaps_updated)(s32 cid, u64 before, u64 after);
    void (*cid_online)(s32 cid);
    void (*cid_offline)(s32 cid);
    s32 (*init_cids)(void);
    s32 (*init)(void);
    void (*exit)(struct scx_exit_info *info);
    u32 dispatch_max_batch;
    u64 flags;
    u32 timeout_ms;
    u32 exit_dump_len;
    u64 hotplug_seq;
    u32 cid_shard_size;
    u32 rescue_bandwidth_ppt;
    u32 rescue_quantum_us;
    u64 sub_cgroup_id;
    char name[SCX_OPS_NAME_LEN];
    void *priv;
    char __end[0];
};

✨ Members ✨

okay this section is short but it's doing a LOT of heavy lifting, so pay attention bestie 🫢


πŸ’œ Description πŸ’œ

So basically it mirrors struct sched_ext_ops, bestie β€” except wherever cpu/cpumask showed up, it's been swapped for cid/cmask where applicable. glow-up behavior, fr fr.

And here's the part that's lowkey the coolest: the layout up to and including priv matches sched_ext_ops byte-for-byte. And no, they're not just trusting vibes on that β€” it's verified by BUILD_BUG_ON checks at scx_init time 🫑 so shared field offsets work for both struct types in bpf_scx_init_member and bpf_scx_check_member. shared offsets = the friendship bracelet of structs, honestly.

Also!! The deprecated cpu_acquire/cpu_release callbacks that are hanging out at the tail of sched_ext_ops? They are omitted here entirely. gone. not invited. πŸ’€

πŸŽ€ Differences from sched_ext_ops πŸŽ€

  • select_cpu -> select_cid (returns cid)
  • dispatch -> dispatch (cpu arg is now cid)
  • update_idle -> update_idle (cpu arg is now cid)
  • set_cpumask -> set_cmask (cmask instead of cpumask)
  • enable -> enable (takes struct scx_enable_args)
  • cpu_online -> cid_online
  • cpu_offline -> cid_offline
  • dump_cpu -> dump_cid
  • cgroup_* -> cpuctl_* (they track the cgroup cpu controller)
  • cpu_acquire/cpu_release -> not present (deprecated in sched_ext_ops)

⚠️ ok this part is important, don't scroll past it: BPF schedulers using this type cannot call cpu-form scx_bpf_* kfuncs. use the cid-form variants instead, periodt. and it's not a suggestion either β€” it's enforced at BPF verifier time via scx_kfunc_context_filter branching on prog->aux->st_ops. so like... the verifier will simply know. πŸ’…

For the actual callback documentation, go read sched_ext_ops β€” it's all there, she's the main character, this one's the remix. πŸ‘‘


🌈 SEE ALSO 🌈

Kernel file ./kernel/sched/ext/internal.h scx_add_event(9), __scx_add_event(9), struct scx_enable_args(9), struct sched_ext_ops(9), scx_arena_to_kaddr(9), scx_kaddr_to_arena(9), DEFINE_SCX_COMPAT_MARKER(9), scx_root_protected_live(9), scx_root_protected(9), scx_bypass_dsp_enabled(9), scx_ops_sanitize_err(9), scx_has_subs(9), scx_task_sched(9), scx_task_sched_rcu(9), scx_task_on_sched(9), scx_prog_sched(9), scx_parent(9)


and that's the whole page, bestie πŸ“ mwah πŸ’‹ β€” sign-off time: this lil gem lives at ./kernel/sched/ext and it's dated October 2026. go forth and schedule things. πŸ§šβ€β™€οΈ slay ✨

πŸ“¦ where this page comes from