[PATCH v3 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe

From: Tao Cui

Date: Tue Sep 01 2026 - 22:50:34 EST


From: Tao Cui <cuitao@xxxxxxxxxx>

cgv_node_less() compares cvtimes with a plain <, which misorders once
cvtime wraps: the wrapped node lands at the front of the tree while
the unwrapped ones get stuck behind it. Each CPU picking a cgroup
charges it a full slice, making wrap occur earlier than a naive
estimate might suggest.

Use time_before() instead. cgrp_cap_budget() bounds the lag behind
cvtime_now, while the lead is bounded by the slice charge plus pending
cvtime_delta on re-insertion, so the cyclic ordering assumptions of
time_before() hold.

Fixes: a4103eacc2ab ("sched_ext: Add a cgroup scheduler which uses flattened hierarchy")
Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Link: https://lore.kernel.org/r/3f1ce004-e259-4e72-a5f7-14a5050053bd@xxxxxxxxx
Signed-off-by: Tao Cui <cuitao@xxxxxxxxxx>
---
tools/sched_ext/scx_flatcg.bpf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/sched_ext/scx_flatcg.bpf.c b/tools/sched_ext/scx_flatcg.bpf.c
index 454ebb820c5e..5e6abd0bccb3 100644
--- a/tools/sched_ext/scx_flatcg.bpf.c
+++ b/tools/sched_ext/scx_flatcg.bpf.c
@@ -144,7 +144,7 @@ static bool cgv_node_less(struct bpf_rb_node *a, const struct bpf_rb_node *b)
cgc_a = container_of(a, struct cgv_node, rb_node);
cgc_b = container_of(b, struct cgv_node, rb_node);

- return cgc_a->cvtime < cgc_b->cvtime;
+ return time_before(cgc_a->cvtime, cgc_b->cvtime);
}

static struct fcg_cpu_ctx *find_cpu_ctx(void)
--
2.43.0