@@ -203,6 +203,11 @@ struct scx_exit_task_args {
203203struct scx_cgroup_init_args {
204204 /* the weight of the cgroup [1..10000] */
205205 u32 weight ;
206+
207+ /* bandwidth control parameters from cpu.max and cpu.max.burst */
208+ u64 bw_period_us ;
209+ u64 bw_quota_us ;
210+ u64 bw_burst_us ;
206211};
207212
208213enum scx_cpu_preempt_reason {
@@ -664,9 +669,31 @@ struct sched_ext_ops {
664669 * @cgrp: cgroup whose weight is being updated
665670 * @weight: new weight [1..10000]
666671 *
667- * Update @tg 's weight to @weight.
672+ * Update @cgrp 's weight to @weight.
668673 */
669674 void (* cgroup_set_weight )(struct cgroup * cgrp , u32 weight );
675+
676+ /**
677+ * @cgroup_set_bandwidth: A cgroup's bandwidth is being changed
678+ * @cgrp: cgroup whose bandwidth is being updated
679+ * @period_us: bandwidth control period
680+ * @quota_us: bandwidth control quota
681+ * @burst_us: bandwidth control burst
682+ *
683+ * Update @cgrp's bandwidth control parameters. This is from the cpu.max
684+ * cgroup interface.
685+ *
686+ * @quota_us / @period_us determines the CPU bandwidth @cgrp is entitled
687+ * to. For example, if @period_us is 1_000_000 and @quota_us is
688+ * 2_500_000. @cgrp is entitled to 2.5 CPUs. @burst_us can be
689+ * interpreted in the same fashion and specifies how much @cgrp can
690+ * burst temporarily. The specific control mechanism and thus the
691+ * interpretation of @period_us and burstiness is upto to the BPF
692+ * scheduler.
693+ */
694+ void (* cgroup_set_bandwidth )(struct cgroup * cgrp ,
695+ u64 period_us , u64 quota_us , u64 burst_us );
696+
670697#endif /* CONFIG_EXT_GROUP_SCHED */
671698
672699 /*
@@ -4059,6 +4086,8 @@ static bool scx_cgroup_enabled;
40594086void scx_tg_init (struct task_group * tg )
40604087{
40614088 tg -> scx .weight = CGROUP_WEIGHT_DFL ;
4089+ tg -> scx .bw_period_us = default_bw_period_us ();
4090+ tg -> scx .bw_quota_us = RUNTIME_INF ;
40624091}
40634092
40644093int scx_tg_online (struct task_group * tg )
@@ -4073,7 +4102,10 @@ int scx_tg_online(struct task_group *tg)
40734102 if (scx_cgroup_enabled ) {
40744103 if (SCX_HAS_OP (sch , cgroup_init )) {
40754104 struct scx_cgroup_init_args args =
4076- { .weight = tg -> scx .weight };
4105+ { .weight = tg -> scx .weight ,
4106+ .bw_period_us = tg -> scx .bw_period_us ,
4107+ .bw_quota_us = tg -> scx .bw_quota_us ,
4108+ .bw_burst_us = tg -> scx .bw_burst_us };
40774109
40784110 ret = SCX_CALL_OP_RET (sch , SCX_KF_UNLOCKED , cgroup_init ,
40794111 NULL , tg -> css .cgroup , & args );
@@ -4225,6 +4257,27 @@ void scx_group_set_idle(struct task_group *tg, bool idle)
42254257 /* TODO: Implement ops->cgroup_set_idle() */
42264258}
42274259
4260+ void scx_group_set_bandwidth (struct task_group * tg ,
4261+ u64 period_us , u64 quota_us , u64 burst_us )
4262+ {
4263+ struct scx_sched * sch = scx_root ;
4264+
4265+ percpu_down_read (& scx_cgroup_rwsem );
4266+
4267+ if (scx_cgroup_enabled && SCX_HAS_OP (sch , cgroup_set_bandwidth ) &&
4268+ (tg -> scx .bw_period_us != period_us ||
4269+ tg -> scx .bw_quota_us != quota_us ||
4270+ tg -> scx .bw_burst_us != burst_us ))
4271+ SCX_CALL_OP (sch , SCX_KF_UNLOCKED , cgroup_set_bandwidth , NULL ,
4272+ tg_cgrp (tg ), period_us , quota_us , burst_us );
4273+
4274+ tg -> scx .bw_period_us = period_us ;
4275+ tg -> scx .bw_quota_us = quota_us ;
4276+ tg -> scx .bw_burst_us = burst_us ;
4277+
4278+ percpu_up_read (& scx_cgroup_rwsem );
4279+ }
4280+
42284281static void scx_cgroup_lock (void )
42294282{
42304283 percpu_down_write (& scx_cgroup_rwsem );
@@ -4400,7 +4453,12 @@ static int scx_cgroup_init(struct scx_sched *sch)
44004453 rcu_read_lock ();
44014454 css_for_each_descendant_pre (css , & root_task_group .css ) {
44024455 struct task_group * tg = css_tg (css );
4403- struct scx_cgroup_init_args args = { .weight = tg -> scx .weight };
4456+ struct scx_cgroup_init_args args = {
4457+ .weight = tg -> scx .weight ,
4458+ .bw_period_us = tg -> scx .bw_period_us ,
4459+ .bw_quota_us = tg -> scx .bw_quota_us ,
4460+ .bw_burst_us = tg -> scx .bw_burst_us ,
4461+ };
44044462
44054463 if ((tg -> scx .flags &
44064464 (SCX_TG_ONLINE | SCX_TG_INITED )) != SCX_TG_ONLINE )
@@ -5902,6 +5960,7 @@ static s32 sched_ext_ops__cgroup_prep_move(struct task_struct *p, struct cgroup
59025960static void sched_ext_ops__cgroup_move (struct task_struct * p , struct cgroup * from , struct cgroup * to ) {}
59035961static void sched_ext_ops__cgroup_cancel_move (struct task_struct * p , struct cgroup * from , struct cgroup * to ) {}
59045962static void sched_ext_ops__cgroup_set_weight (struct cgroup * cgrp , u32 weight ) {}
5963+ static void sched_ext_ops__cgroup_set_bandwidth (struct cgroup * cgrp , u64 period_us , u64 quota_us , u64 burst_us ) {}
59055964#endif
59065965static void sched_ext_ops__cpu_online (s32 cpu ) {}
59075966static void sched_ext_ops__cpu_offline (s32 cpu ) {}
@@ -5939,6 +5998,7 @@ static struct sched_ext_ops __bpf_ops_sched_ext_ops = {
59395998 .cgroup_move = sched_ext_ops__cgroup_move ,
59405999 .cgroup_cancel_move = sched_ext_ops__cgroup_cancel_move ,
59416000 .cgroup_set_weight = sched_ext_ops__cgroup_set_weight ,
6001+ .cgroup_set_bandwidth = sched_ext_ops__cgroup_set_bandwidth ,
59426002#endif
59436003 .cpu_online = sched_ext_ops__cpu_online ,
59446004 .cpu_offline = sched_ext_ops__cpu_offline ,
0 commit comments