* [PATCH 0/2] sched_ext: fix wraparound-unsafe vtime orderings
@ 2026-09-01 2:40 Tao Cui
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
2026-09-01 2:40 ` [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe Tao Cui
0 siblings, 2 replies; 9+ messages in thread
From: Tao Cui @ 2026-09-01 2:40 UTC (permalink / raw)
To: tj, void
Cc: arighi, changwoo, michalblk, liwanwu, sched-ext, linux-kernel,
bpf, cui.tao, Tao Cui
From: Tao Cui <cuitao@kylinos.cn>
Two spots order tasks by 64-bit virtual time with comparisons that
break when the values are far apart: the kernel's vtime DSQ priority
queue and scx_flatcg's cgroup tree. They need opposite fixes, which
is the point of this series.
The kernel's scx_dsq_priq_less() compares with time_before64(), i.e.
(s64)(a - b) < 0. That is only a valid ordering when all values in
the queue are less than 2^63 apart. CFS upholds that invariant with
min_vruntime clamping; sched_ext cannot, because dsq_vtime comes
straight from the BPF scheduler. A scheduler that inserts vtimes
wider than 2^63 apart into one DSQ gets the inverted order -- the
tasks it placed last run first while the rest starve. Patch 1
switches to a plain u64 comparison, which is a total order and always
honors the requested order; it reproduces the inversion with a probe
scheduler and verifies the fix.
scx_flatcg's cgv_node_less() has the inverse problem: it compares
with a plain <, which misorders once cvtime wraps. There the cyclic
(s64)(a - b) < 0 comparison from patch 1's bug is the correct fix,
because flatcg does uphold the spread invariant --
cgrp_cap_budget() clamps every node to within max_budget behind
cvtime_now -- and the cyclic comparison also carries the ordering
correctly across the natural 2^64 wrap, which a plain comparison
would not.
So: same bug family, opposite fixes, each justified by whether the
spread invariant exists. This is also why the naive "use
time_before64 everywhere" suggestion doesn't hold -- without the
invariant it is exactly the inversion patch 1 fixes.
Tao Cui (2):
sched_ext: fix vtime priority queue inversion on wide vtime spread
sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe
kernel/sched/ext/ext.c | 3 ++-
tools/sched_ext/scx_flatcg.bpf.c | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread
2026-09-01 2:40 [PATCH 0/2] sched_ext: fix wraparound-unsafe vtime orderings Tao Cui
@ 2026-09-01 2:40 ` Tao Cui
2026-09-01 2:54 ` sashiko-bot
` (2 more replies)
2026-09-01 2:40 ` [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe Tao Cui
1 sibling, 3 replies; 9+ messages in thread
From: Tao Cui @ 2026-09-01 2:40 UTC (permalink / raw)
To: tj, void
Cc: arighi, changwoo, michalblk, liwanwu, sched-ext, linux-kernel,
bpf, cui.tao, Tao Cui
From: Tao Cui <cuitao@kylinos.cn>
scx_dsq_priq_less() compares dsq_vtime with time_before64(), a cyclic
comparison that is only valid when the values in the queue are less
than 2^63 apart. Unlike CFS, which enforces that invariant with
min_vruntime clamping, sched_ext takes dsq_vtime directly from the BPF
scheduler and cannot bound the spread. A scheduler that inserts tasks
with vtimes wider than 2^63 apart into one DSQ gets the order inverted:
the tasks it placed last run first and the rest starve. Reproduced with
a probe scheduler assigning half its tasks vtimes near 0 and the other
half vtimes above 2^63 -- four of eight busy tasks monopolized the CPU
while the other four starved.
Compare with plain u64 < instead, which is a total order and always
honors the order the scheduler asked for. The transient misordering
around the natural 2^64 wrap is the same class of anomaly the cyclic
comparison trades it for, but bounded.
Fixes: 06e51be3d5e7 ("sched_ext: Add vtime-ordered priority queue to dispatch_q's")
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
kernel/sched/ext/ext.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
index 8041c87a3562..dd0ce01370d1 100644
--- a/kernel/sched/ext/ext.c
+++ b/kernel/sched/ext/ext.c
@@ -1417,7 +1417,8 @@ static bool scx_dsq_priq_less(struct rb_node *node_a,
const struct task_struct *b =
container_of(node_b, struct task_struct, scx.dsq_priq);
- return time_before64(a->scx.dsq_vtime, b->scx.dsq_vtime);
+ /* dsq_vtime is arbitrary BPF input: keep a total order */
+ return a->scx.dsq_vtime < b->scx.dsq_vtime;
}
static void dsq_inc_nr(struct scx_dispatch_q *dsq, struct task_struct *p, u64 enq_flags)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe
2026-09-01 2:40 [PATCH 0/2] sched_ext: fix wraparound-unsafe vtime orderings Tao Cui
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
@ 2026-09-01 2:40 ` Tao Cui
2026-09-01 2:51 ` sashiko-bot
2026-09-01 3:54 ` bot+bpf-ci
1 sibling, 2 replies; 9+ messages in thread
From: Tao Cui @ 2026-09-01 2:40 UTC (permalink / raw)
To: tj, void
Cc: arighi, changwoo, michalblk, liwanwu, sched-ext, linux-kernel,
bpf, cui.tao, Tao Cui, Sashiko
From: Tao Cui <cuitao@kylinos.cn>
cgv_node_less() compares cvtimes with a plain <, which breaks once
cvtime wraps. A weight-1 cgroup in a hierarchy summing to 10000
advances cvtime at up to 10000x wall time, so 2^64 ns of cvtime is
weeks of continuous saturation away -- unlikely but reachable on a
long-running host. At the wrap instant the plain comparison puts the
wrapped node behind everything else permanently.
Compare with (s64)(a - b) < 0 instead, as CFS does for vruntime. A
cyclic comparison is valid as an rbtree comparator only because
cgrp_cap_budget() clamps every node to within max_budget behind
cvtime_now, so any two nodes are far less than 2^63 apart and the
cyclic order agrees with the true order.
Compile-tested and smoke-tested in a VM: weight distribution and
dispatch unaffected.
Fixes: 7b742aa2c2c9 ("sched_ext: Add a cgroup scheduler which uses flattened hierarchy")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/r/3f1ce004-e259-4e72-a5f7-14a5050053bd@linux.dev
Signed-off-by: Tao Cui <cuitao@kylinos.cn>
---
tools/sched_ext/scx_flatcg.bpf.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/sched_ext/scx_flatcg.bpf.c b/tools/sched_ext/scx_flatcg.bpf.c
index 454ebb820c5e..be03b409db5e 100644
--- a/tools/sched_ext/scx_flatcg.bpf.c
+++ b/tools/sched_ext/scx_flatcg.bpf.c
@@ -144,7 +144,8 @@ 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;
+ /* wrap-safe: cap_budget keeps nodes within 2^63 of each other */
+ return (s64)(cgc_a->cvtime - cgc_b->cvtime) < 0;
}
static struct fcg_cpu_ctx *find_cpu_ctx(void)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe
2026-09-01 2:40 ` [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe Tao Cui
@ 2026-09-01 2:51 ` sashiko-bot
2026-09-01 3:54 ` bot+bpf-ci
1 sibling, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-09-01 2:51 UTC (permalink / raw)
To: Tao Cui; +Cc: bpf, sched-ext
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Incorrect usage of `__sync_fetch_and_sub` with a self-referencing argument leads to double-counting of concurrent time additions.
--
commit aa8a669e2d8a03160f8c5bfda45d4fd749f2352c
Author: Tao Cui <cuitao@kylinos.cn>
sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe
cgv_node_less() compares cvtimes with a plain <, which breaks once
cvtime wraps. Compare with (s64)(a - b) < 0 instead, as CFS does for vruntime.
A cyclic comparison is valid as an rbtree comparator only because
cgrp_cap_budget() clamps every node to within max_budget behind
cvtime_now.
Link: https://lore.kernel.org/r/3f1ce004-e259-4e72-a5f7-14a5050053bd@linux.dev
> diff --git a/tools/sched_ext/scx_flatcg.bpf.c b/tools/sched_ext/scx_flatcg.bpf.c
> index fec3595818269..3a25cfdc97092 100644
> --- a/tools/sched_ext/scx_flatcg.bpf.c
> +++ b/tools/sched_ext/scx_flatcg.bpf.c
> @@ -144,7 +144,8 @@ 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;
> + /* wrap-safe: cap_budget keeps nodes within 2^63 of each other */
> + return (s64)(cgc_a->cvtime - cgc_b->cvtime) < 0;
> }
>
> static struct fcg_cpu_ctx *find_cpu_ctx(void)
[ ... ]
[Severity: High]
This is a pre-existing issue, but does using __sync_fetch_and_sub() with a
self-referencing argument cause double-counting of concurrent time additions?
In tools/sched_ext/scx_flatcg.bpf.c:cgrp_cap_budget():
delta = __sync_fetch_and_sub(&cgc->cvtime_delta, cgc->cvtime_delta);
If fcg_stopping() concurrently updates cgc->cvtime_delta using
__sync_fetch_and_add() without holding cgv_tree_lock, can this
sequence occur?
CPU 1 executes cgrp_cap_budget() and reads the second argument (the amount
to subtract), getting the current value (e.g., X).
CPU 2 executes fcg_stopping() and concurrently adds Y, making the memory
value X + Y.
CPU 1 executes the atomic subtract of X from X + Y, returning the old
memory value of X + Y, but leaving Y in memory.
CPU 1 then processes delta as X + Y, while Y remains in memory.
Could this result in the concurrent addition Y being processed immediately,
and then remaining in memory to be processed again later, incorrectly
calculating the CPU share for the cgroup?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260901024038.730424-1-cui.tao@linux.dev?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
@ 2026-09-01 2:54 ` sashiko-bot
2026-09-01 6:47 ` Andrea Righi
2026-09-01 8:29 ` Tejun Heo
2 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-09-01 2:54 UTC (permalink / raw)
To: Tao Cui; +Cc: bpf, sched-ext
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The patch silently breaks the established cyclic `vtime` ordering contract by switching to an absolute `<` comparison, causing permanent task starvation upon wraparound and contradicting existing kfunc documentation and selftests.
--
commit b0708e9275ee1ffad12d1e3811001b6d6ee4c741
Author: Tao Cui <cuitao@kylinos.cn>
sched_ext: fix vtime priority queue inversion on wide vtime spread
This commit replaces the time_before64() cyclic comparison in
scx_dsq_priq_less() with a plain less-than operation to prevent priority queue
inversion when vtimes have a wide spread.
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index 18183062f751c..db1ea9054c0ca 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -1356,7 +1356,8 @@ static bool scx_dsq_priq_less(struct rb_node *node_a,
> const struct task_struct *b =
> container_of(node_b, struct task_struct, scx.dsq_priq);
>
> - return time_before64(a->scx.dsq_vtime, b->scx.dsq_vtime);
> + /* dsq_vtime is arbitrary BPF input: keep a total order */
> + return a->scx.dsq_vtime < b->scx.dsq_vtime;
[Severity: High]
Does this break the established cyclic vtime ordering contract and cause
permanent task starvation upon wraparound?
If a BPF scheduler assigns vtime to tasks, and the vtime advances and
eventually wraps around U64_MAX, tasks that are in the queue at the time of
wraparound (with vtime near U64_MAX) will be indefinitely starved. This happens
because new post-wrap tasks (with small absolute vtimes) will be strictly less
than the old ones and placed ahead of them.
The user-facing kfunc documentation for __scx_bpf_dsq_insert_vtime() in
kernel/sched/ext/ext.c still explicitly promises the cyclic wrapping behavior:
* @args->vtime ordering is according to time_before64() which considers
* wrapping. A numerically larger vtime may indicate an earlier position in the
* ordering and vice-versa.
Additionally, BPF schedulers still actively rely on the cyclic vtime semantics,
as seen in tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c:
static inline bool vtime_before(u64 a, u64 b)
{
return (s64)(a - b) < 0;
}
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260901024038.730424-1-cui.tao@linux.dev?part=1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe
2026-09-01 2:40 ` [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe Tao Cui
2026-09-01 2:51 ` sashiko-bot
@ 2026-09-01 3:54 ` bot+bpf-ci
1 sibling, 0 replies; 9+ messages in thread
From: bot+bpf-ci @ 2026-09-01 3:54 UTC (permalink / raw)
To: cui.tao, tj, void
Cc: arighi, changwoo, michalblk, liwanwu, sched-ext, linux-kernel,
bpf, cui.tao, cuitao, sashiko-bot, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1751 bytes --]
> cgv_node_less() compares cvtimes with a plain <, which breaks once
> cvtime wraps. A weight-1 cgroup in a hierarchy summing to 10000
> advances cvtime at up to 10000x wall time, so 2^64 ns of cvtime is
> weeks of continuous saturation away -- unlikely but reachable on a
> long-running host. At the wrap instant the plain comparison puts the
> wrapped node behind everything else permanently.
>
> Compare with (s64)(a - b) < 0 instead, as CFS does for vruntime. A
> cyclic comparison is valid as an rbtree comparator only because
> cgrp_cap_budget() clamps every node to within max_budget behind
> cvtime_now, so any two nodes are far less than 2^63 apart and the
> cyclic order agrees with the true order.
>
> Compile-tested and smoke-tested in a VM: weight distribution and
> dispatch unaffected.
>
> Fixes: 7b742aa2c2c9 ("sched_ext: Add a cgroup scheduler which uses flattened hierarchy")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/r/3f1ce004-e259-4e72-a5f7-14a5050053bd@linux.dev
> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
Is the Fixes: tag correct? The tag references commit 7b742aa2c2c9, which
does not exist in this repository. The bug was actually introduced by
commit a4103eacc2ab4 ("sched_ext: Add a cgroup scheduler which uses
flattened hierarchy"), which added the buggy plain comparison
'cgc_a->cvtime < cgc_b->cvtime' that this commit fixes. Should the tag
be:
Fixes: a4103eacc2ab4 ("sched_ext: Add a cgroup scheduler which uses flattened hierarchy")
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/33465241568
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
2026-09-01 2:54 ` sashiko-bot
@ 2026-09-01 6:47 ` Andrea Righi
2026-09-01 9:44 ` Tao Cui
2026-09-01 8:29 ` Tejun Heo
2 siblings, 1 reply; 9+ messages in thread
From: Andrea Righi @ 2026-09-01 6:47 UTC (permalink / raw)
To: Tao Cui
Cc: tj, void, changwoo, michalblk, liwanwu, sched-ext, linux-kernel,
bpf, Tao Cui
Hi Tao,
On Tue, Sep 01, 2026 at 10:40:37AM +0800, Tao Cui wrote:
> From: Tao Cui <cuitao@kylinos.cn>
>
> scx_dsq_priq_less() compares dsq_vtime with time_before64(), a cyclic
> comparison that is only valid when the values in the queue are less
> than 2^63 apart. Unlike CFS, which enforces that invariant with
> min_vruntime clamping, sched_ext takes dsq_vtime directly from the BPF
> scheduler and cannot bound the spread. A scheduler that inserts tasks
> with vtimes wider than 2^63 apart into one DSQ gets the order inverted:
> the tasks it placed last run first and the rest starve. Reproduced with
> a probe scheduler assigning half its tasks vtimes near 0 and the other
> half vtimes above 2^63 -- four of eight busy tasks monopolized the CPU
> while the other four starved.
>
> Compare with plain u64 < instead, which is a total order and always
> honors the order the scheduler asked for. The transient misordering
> around the natural 2^64 wrap is the same class of anomaly the cyclic
> comparison trades it for, but bounded.
I don't think switching to plain u64 ordering is safe here.
The current scx_bpf_dsq_insert_vtime() documentation explicitly defines the
ordering in terms of time_before64(), including wraparound. For example:
a = U64_MAX - 5
b = 3
a is earlier than b in cyclic vtime ordering. time_before64(a, b) correctly
returns true, while plain a < b would place b first.
Moreover, this is not a short transient. If post-wrap tasks continue to be
reinserted with small vtimes, a can remain behind them until their vtime
traverses almost the entire u64 range, resulting in effective starvation.
Can we preserve time_before64() and document or enforce the half-range
requirement instead?
Thanks,
-Andrea
>
> Fixes: 06e51be3d5e7 ("sched_ext: Add vtime-ordered priority queue to dispatch_q's")
> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
> ---
> kernel/sched/ext/ext.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
> index 8041c87a3562..dd0ce01370d1 100644
> --- a/kernel/sched/ext/ext.c
> +++ b/kernel/sched/ext/ext.c
> @@ -1417,7 +1417,8 @@ static bool scx_dsq_priq_less(struct rb_node *node_a,
> const struct task_struct *b =
> container_of(node_b, struct task_struct, scx.dsq_priq);
>
> - return time_before64(a->scx.dsq_vtime, b->scx.dsq_vtime);
> + /* dsq_vtime is arbitrary BPF input: keep a total order */
> + return a->scx.dsq_vtime < b->scx.dsq_vtime;
> }
>
> static void dsq_inc_nr(struct scx_dispatch_q *dsq, struct task_struct *p, u64 enq_flags)
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
2026-09-01 2:54 ` sashiko-bot
2026-09-01 6:47 ` Andrea Righi
@ 2026-09-01 8:29 ` Tejun Heo
2 siblings, 0 replies; 9+ messages in thread
From: Tejun Heo @ 2026-09-01 8:29 UTC (permalink / raw)
To: Tao Cui
Cc: void, arighi, changwoo, michalblk, liwanwu, sched-ext,
linux-kernel, bpf, Tao Cui
Hello,
On Tue, Sep 01, 2026 at 10:40:37AM +0800, Tao Cui wrote:
...
> than 2^63 apart. Unlike CFS, which enforces that invariant with
> min_vruntime clamping, sched_ext takes dsq_vtime directly from the BPF
> scheduler and cannot bound the spread. A scheduler that inserts tasks
This doesn't make any practical sense. dsq_vtime is by (implicit) definition
a rolling cursor. Please feel free to add documentation if that'd help.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread
2026-09-01 6:47 ` Andrea Righi
@ 2026-09-01 9:44 ` Tao Cui
0 siblings, 0 replies; 9+ messages in thread
From: Tao Cui @ 2026-09-01 9:44 UTC (permalink / raw)
To: Andrea Righi
Cc: cui.tao, tj, void, changwoo, michalblk, liwanwu, sched-ext,
linux-kernel, bpf, Tao Cui
Hello, Andrea, Tejun.
在 2026/9/1 14:47, Andrea Righi 写道:
> Hi Tao,
>
> On Tue, Sep 01, 2026 at 10:40:37AM +0800, Tao Cui wrote:
>> From: Tao Cui <cuitao@kylinos.cn>
>>
>> scx_dsq_priq_less() compares dsq_vtime with time_before64(), a cyclic
>> comparison that is only valid when the values in the queue are less
>> than 2^63 apart. Unlike CFS, which enforces that invariant with
>> min_vruntime clamping, sched_ext takes dsq_vtime directly from the BPF
>> scheduler and cannot bound the spread. A scheduler that inserts tasks
>> with vtimes wider than 2^63 apart into one DSQ gets the order inverted:
>> the tasks it placed last run first and the rest starve. Reproduced with
>> a probe scheduler assigning half its tasks vtimes near 0 and the other
>> half vtimes above 2^63 -- four of eight busy tasks monopolized the CPU
>> while the other four starved.
>>
>> Compare with plain u64 < instead, which is a total order and always
>> honors the order the scheduler asked for. The transient misordering
>> around the natural 2^64 wrap is the same class of anomaly the cyclic
>> comparison trades it for, but bounded.
>
> I don't think switching to plain u64 ordering is safe here.
>
> The current scx_bpf_dsq_insert_vtime() documentation explicitly defines the
> ordering in terms of time_before64(), including wraparound. For example:
>
> a = U64_MAX - 5
> b = 3
>
> a is earlier than b in cyclic vtime ordering. time_before64(a, b) correctly
> returns true, while plain a < b would place b first.
>
> Moreover, this is not a short transient. If post-wrap tasks continue to be
> reinserted with small vtimes, a can remain behind them until their vtime
> traverses almost the entire u64 range, resulting in effective starvation.
>
> Can we preserve time_before64() and document or enforce the half-range
> requirement instead?
>
You're both right, patch 1/2 was wrong. My probe fed values that
violate the rolling-cursor assumption, and the "inversion" was the
API behaving as documented. Dropping 1/2.
I'll send the documentation patch Tejun suggested.
Thanks,
Tao
> Thanks,
> -Andrea
>
>>
>> Fixes: 06e51be3d5e7 ("sched_ext: Add vtime-ordered priority queue to dispatch_q's")
>> Signed-off-by: Tao Cui <cuitao@kylinos.cn>
>> ---
>> kernel/sched/ext/ext.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/kernel/sched/ext/ext.c b/kernel/sched/ext/ext.c
>> index 8041c87a3562..dd0ce01370d1 100644
>> --- a/kernel/sched/ext/ext.c
>> +++ b/kernel/sched/ext/ext.c
>> @@ -1417,7 +1417,8 @@ static bool scx_dsq_priq_less(struct rb_node *node_a,
>> const struct task_struct *b =
>> container_of(node_b, struct task_struct, scx.dsq_priq);
>>
>> - return time_before64(a->scx.dsq_vtime, b->scx.dsq_vtime);
>> + /* dsq_vtime is arbitrary BPF input: keep a total order */
>> + return a->scx.dsq_vtime < b->scx.dsq_vtime;
>> }
>>
>> static void dsq_inc_nr(struct scx_dispatch_q *dsq, struct task_struct *p, u64 enq_flags)
>> --
>> 2.43.0
>>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-01 9:44 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-01 2:40 [PATCH 0/2] sched_ext: fix wraparound-unsafe vtime orderings Tao Cui
2026-09-01 2:40 ` [PATCH 1/2] sched_ext: fix vtime priority queue inversion on wide vtime spread Tao Cui
2026-09-01 2:54 ` sashiko-bot
2026-09-01 6:47 ` Andrea Righi
2026-09-01 9:44 ` Tao Cui
2026-09-01 8:29 ` Tejun Heo
2026-09-01 2:40 ` [PATCH 2/2] sched_ext/scx_flatcg: make cgv_node_less() wraparound-safe Tao Cui
2026-09-01 2:51 ` sashiko-bot
2026-09-01 3:54 ` bot+bpf-ci
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).