History

sched_ext: Make scx_enable() take scx_enable_cmd

Pass struct scx_enable_cmd to scx_enable() rather than unpacking @ops at every call site and re-packing into a fresh cmd inside. bpf_scx_reg() now builds the cmd on its stack and hands it in; scx_enable() just wires up the kthread work and waits. Relocate struct scx_enable_cmd above scx_alloc_and_add_sched() so upcoming patches that also want the cmd can see it. No behavior change.

Tejun Heo committed 6 months ago

Commit c97ce721 parent 1e315c41 file · +23 −23Browse files

Unified · Split

kernel/sched/ext.c+23−23
@@ -6529,6 +6529,19 @@ static struct scx_sched_pnode *alloc_pnode(struct scx_sched *sch, int node) · 6528 unmodified lines
65296529 return pnode;
65306530 }
65316531
6532+/*
6533+ * scx_enable() is offloaded to a dedicated system-wide RT kthread to avoid
6534+ * starvation. During the READY -> ENABLED task switching loop, the calling
6535+ * thread's sched_class gets switched from fair to ext. As fair has higher
6536+ * priority than ext, the calling thread can be indefinitely starved under
6537+ * fair-class saturation, leading to a system hang.
6538+ */
6539+struct scx_enable_cmd {
6540+ struct kthread_work work;
6541+ struct sched_ext_ops *ops;
6542+ int ret;
6543+};
6544+
65326545 /*
65336546 * Allocate and initialize a new scx_sched. @cgrp's reference is always
65346547 * consumed whether the function succeeds or fails.
@@ -6771,19 +6784,6 @@ static int validate_ops(struct scx_sched *sch, const struct sched_ext_ops *ops) · 236 unmodified lines
67716784 return 0;
67726785 }
67736786
6774−/*
6775− * scx_enable() is offloaded to a dedicated system-wide RT kthread to avoid
6776− * starvation. During the READY -> ENABLED task switching loop, the calling
6777− * thread's sched_class gets switched from fair to ext. As fair has higher
6778− * priority than ext, the calling thread can be indefinitely starved under
6779− * fair-class saturation, leading to a system hang.
6780− */
6781−struct scx_enable_cmd {
6782− struct kthread_work work;
6783− struct sched_ext_ops *ops;
6784− int ret;
6785−};
6786−
67876787 static void scx_root_enable_workfn(struct kthread_work *work)
67886788 {
67896789 struct scx_enable_cmd *cmd = container_of(work, struct scx_enable_cmd, work);
@@ -7368,11 +7368,10 @@ static s32 __init scx_cgroup_lifetime_notifier_init(void) · 578 unmodified lines
73687368 core_initcall(scx_cgroup_lifetime_notifier_init);
73697369 #endif /* CONFIG_EXT_SUB_SCHED */
73707370
7371−static s32 scx_enable(struct sched_ext_ops *ops, struct bpf_link *link)
7371+static s32 scx_enable(struct scx_enable_cmd *cmd, struct bpf_link *link)
73727372 {
73737373 static struct kthread_worker *helper;
73747374 static DEFINE_MUTEX(helper_mutex);
7375− struct scx_enable_cmd cmd;
73767375
73777376 if (!cpumask_equal(housekeeping_cpumask(HK_TYPE_DOMAIN),
73787377 cpu_possible_mask)) {
@@ -7396,16 +7395,15 @@ static s32 scx_enable(struct sched_ext_ops *ops, struct bpf_link *link) · 17 unmodified lines
73967395 }
73977396
73987397 #ifdef CONFIG_EXT_SUB_SCHED
7399− if (ops->sub_cgroup_id > 1)
7400− kthread_init_work(&cmd.work, scx_sub_enable_workfn);
7398+ if (cmd->ops->sub_cgroup_id > 1)
7399+ kthread_init_work(&cmd->work, scx_sub_enable_workfn);
74017400 else
74027401 #endif /* CONFIG_EXT_SUB_SCHED */
7403− kthread_init_work(&cmd.work, scx_root_enable_workfn);
7404− cmd.ops = ops;
7402+ kthread_init_work(&cmd->work, scx_root_enable_workfn);
74057403
7406− kthread_queue_work(READ_ONCE(helper), &cmd.work);
7407− kthread_flush_work(&cmd.work);
7408− return cmd.ret;
7404+ kthread_queue_work(READ_ONCE(helper), &cmd->work);
7405+ kthread_flush_work(&cmd->work);
7406+ return cmd->ret;
74097407 }
74107408
74117409
@@ -7577,7 +7575,9 @@ static int bpf_scx_check_member(const struct btf_type *t, · 165 unmodified lines
75777575
75787576 static int bpf_scx_reg(void *kdata, struct bpf_link *link)
75797577 {
7580− return scx_enable(kdata, link);
7578+ struct scx_enable_cmd cmd = { .ops = kdata };
7579+
7580+ return scx_enable(&cmd, link);
75817581 }
75827582
75837583 static void bpf_scx_unreg(void *kdata, struct bpf_link *link)