* [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag()
@ 2026-07-03 9:26 Chen Jinghuang
2026-07-06 16:03 ` Vincent Guittot
0 siblings, 1 reply; 5+ messages in thread
From: Chen Jinghuang @ 2026-07-03 9:26 UTC (permalink / raw)
To: mingo, peterz, juri.lelli, vincent.guittot
Cc: dietmar.eggemann, rostedt, bsegall, mgorman, vschneid,
kprateek.nayak, linux-kernel
While running EEVDF-related test cases, we observed an anomalous
phenomenon where the vruntime of a continuously running scheduling
entity (se) exhibits an overall downward trend.
The test topology and observed behavior are as follows:
CPU 0 CPU 1 / Other CPUs
+----------------------------+ +----------------------------+
| cgroup A cgroup B | | cgroup A cgroup B |
| |- A1 (Run) |- B1 | | |- A2, A3... |- B2, B3...|
| (50us S)| | (Frequent sleep/wake) |
| (10us W)| | |
+----------------------------+ +----------------------------+
|
v
A2/A3 frequent sleep/wake -> Frequent reweight of gse(A) on CPU 0
-> Triggers vlag clamping -> Unidirectional avruntime drift
-> gse->vruntime drops abnormally (while gse weight remains stable)
According to function_graph traces, frequent sleep/wake cycles of
sibling tasks within the same cgroup cause the running task to repeatedly
trigger update_cfs_cgroup() -> reweight_entity().
The root cause appears to point to the entity_lag() boundary limit
introduced in `reweight_entity()` to prevent overflows. During repeated
weight scaling, this limit introduces an asymmetric cumulative error.
Connsider an example here where se->vruntime > avruntime:
1. Downscale:
se->vlag = entity_lag(cfs_rq, se, avruntime);
se->vlag = div64_long(se->vlag * old_weight, weight);
se->vruntime = avruntime - se->vlag;
If the calculated vlag exceeds the limit boundary, it is clamped.
This causes the scaled vlag to be bigger than its theoretical value,
making the resulting se->vruntime smaller than it should be (forced
closer to avruntime).
2. Upscale:
Because se->vruntime already carries the clamping error from the
previous step, it implicitly shifts the subsequent global avruntime
computation trajectory. When the weight is restored, se->vruntime
deviates from its original true value, preventing the true vlag from
being reconstructed and leading to a unidirectional avruntime drift.
Under frequent cgroup reweighting, this asymmetric truncation error
accumulates, causing a unidirectional downward drift of vruntime.
Regarding this vlag limit mechanism in reweight_entity(), we would like
to raise a few questions for discussion:
Question 1: Is this deviation of se->vruntime expected?
For a currently running entity (curr se), due to RUN_TO_PARITY, it
typically operates in a state where se->vruntime > avruntime. During
reweighting, the limit forces its vruntime downward (closer to avruntime),
while attributes like deadline remain unaffected by the limit.
Question 2: Is the unidirectional drift of avruntime reasonable?
Since avruntime = avg_vruntime(), the deviation of se->vruntime
before and after reweighting (while its weight remains unchanged) shifts
the global avruntime downward. According to EEVDF core principles,
avruntime should remain invariant across weight changes.
(https://lore.kernel.org/lkml/20260415211149.2658910-1-jstultz@google.com/),
Question 3: Is the reduction of avruntime fair to other entities?
A non-functional reduction in global avruntime passively decreases the
se->vlag of other queued entities on the runqueue, which practically
worsens the starvation of those tasks.
Question 4: Does this lead to complete preemption suppression?
In entity_tick -> update_deadline, because curr->vruntime is abnormally
pulled down by the clamping error while its deadline is unchanged, the
condition vruntime < deadline can be continuously satisfied at every
tick. This skips resched_curr(), suppressing preemption until the
frequent reweighting stops or curr's vlag falls back within the limit.
While entity_lag() was originally introduced to prevent overflow-induced
NULL pointer dereferences, given its significant impact on EEVDF fairness,
should the necessity and implementation of this limit be reconsidered?
Analyzed-by: Hui Tang <tanghui20@huawei.com>
Analyzed-by: Zhang Qiao <zhangqiao22@huawei.com>
Analyzed-by: Zicheng Qu <quzicheng@huawei.com>
Analyzed-by: Chen Jinghuang <chenjinghuang2@huawei.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag()
2026-07-03 9:26 [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag() Chen Jinghuang
@ 2026-07-06 16:03 ` Vincent Guittot
2026-07-07 12:51 ` chenjinghuang
0 siblings, 1 reply; 5+ messages in thread
From: Vincent Guittot @ 2026-07-06 16:03 UTC (permalink / raw)
To: Chen Jinghuang
Cc: mingo, peterz, juri.lelli, dietmar.eggemann, rostedt, bsegall,
mgorman, vschneid, kprateek.nayak, linux-kernel
On Fri, 3 Jul 2026 at 11:50, Chen Jinghuang <chenjinghuang2@huawei.com> wrote:
>
> While running EEVDF-related test cases, we observed an anomalous
> phenomenon where the vruntime of a continuously running scheduling
> entity (se) exhibits an overall downward trend.
>
> The test topology and observed behavior are as follows:
>
> CPU 0 CPU 1 / Other CPUs
> +----------------------------+ +----------------------------+
> | cgroup A cgroup B | | cgroup A cgroup B |
> | |- A1 (Run) |- B1 | | |- A2, A3... |- B2, B3...|
> | (50us S)| | (Frequent sleep/wake) |
> | (10us W)| | |
> +----------------------------+ +----------------------------+
> |
> v
> A2/A3 frequent sleep/wake -> Frequent reweight of gse(A) on CPU 0
> -> Triggers vlag clamping -> Unidirectional avruntime drift
> -> gse->vruntime drops abnormally (while gse weight remains stable)
>
> According to function_graph traces, frequent sleep/wake cycles of
> sibling tasks within the same cgroup cause the running task to repeatedly
> trigger update_cfs_cgroup() -> reweight_entity().
>
> The root cause appears to point to the entity_lag() boundary limit
> introduced in `reweight_entity()` to prevent overflows. During repeated
> weight scaling, this limit introduces an asymmetric cumulative error.
> Connsider an example here where se->vruntime > avruntime:
>
> 1. Downscale:
> se->vlag = entity_lag(cfs_rq, se, avruntime);
The clamp applied in entity_lag() should "in theory never" happen.
Do you have more details to share about your setup?
Which kernel version do you use ? A number of changes have been queued
recently that should ensure that the vlag never goes above the
theoretical limit.
How many CPUs are in the system ?
Is there other tasks running in the cgroups ?
Could you try to run without RUN_TO_PARITY ?
echo NO_RUN_TO_PARITY > /sys/kernel/debug/sched/features
Do you set the share of task groups to particular values?
Do you change the slice of the tasks ?
Note that even without clamping, part of the vlag is lost in div64_long
> se->vlag = div64_long(se->vlag * old_weight, weight);
> se->vruntime = avruntime - se->vlag;
>
> If the calculated vlag exceeds the limit boundary, it is clamped.
> This causes the scaled vlag to be bigger than its theoretical value,
> making the resulting se->vruntime smaller than it should be (forced
> closer to avruntime).
>
> 2. Upscale:
> Because se->vruntime already carries the clamping error from the
> previous step, it implicitly shifts the subsequent global avruntime
> computation trajectory. When the weight is restored, se->vruntime
> deviates from its original true value, preventing the true vlag from
> being reconstructed and leading to a unidirectional avruntime drift.
>
> Under frequent cgroup reweighting, this asymmetric truncation error
> accumulates, causing a unidirectional downward drift of vruntime.
>
> Regarding this vlag limit mechanism in reweight_entity(), we would like
> to raise a few questions for discussion:
>
> Question 1: Is this deviation of se->vruntime expected?
> For a currently running entity (curr se), due to RUN_TO_PARITY, it
> typically operates in a state where se->vruntime > avruntime. During
> reweighting, the limit forces its vruntime downward (closer to avruntime),
> while attributes like deadline remain unaffected by the limit.
>
> Question 2: Is the unidirectional drift of avruntime reasonable?
> Since avruntime = avg_vruntime(), the deviation of se->vruntime
> before and after reweighting (while its weight remains unchanged) shifts
> the global avruntime downward. According to EEVDF core principles,
> avruntime should remain invariant across weight changes.
> (https://lore.kernel.org/lkml/20260415211149.2658910-1-jstultz@google.com/),
>
> Question 3: Is the reduction of avruntime fair to other entities?
> A non-functional reduction in global avruntime passively decreases the
> se->vlag of other queued entities on the runqueue, which practically
> worsens the starvation of those tasks.
>
> Question 4: Does this lead to complete preemption suppression?
> In entity_tick -> update_deadline, because curr->vruntime is abnormally
> pulled down by the clamping error while its deadline is unchanged, the
> condition vruntime < deadline can be continuously satisfied at every
> tick. This skips resched_curr(), suppressing preemption until the
> frequent reweighting stops or curr's vlag falls back within the limit.
>
> While entity_lag() was originally introduced to prevent overflow-induced
> NULL pointer dereferences, given its significant impact on EEVDF fairness,
> should the necessity and implementation of this limit be reconsidered?
>
> Analyzed-by: Hui Tang <tanghui20@huawei.com>
> Analyzed-by: Zhang Qiao <zhangqiao22@huawei.com>
> Analyzed-by: Zicheng Qu <quzicheng@huawei.com>
> Analyzed-by: Chen Jinghuang <chenjinghuang2@huawei.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag()
2026-07-06 16:03 ` Vincent Guittot
@ 2026-07-07 12:51 ` chenjinghuang
2026-07-07 14:52 ` Vincent Guittot
0 siblings, 1 reply; 5+ messages in thread
From: chenjinghuang @ 2026-07-07 12:51 UTC (permalink / raw)
To: Vincent Guittot
Cc: mingo, peterz, juri.lelli, dietmar.eggemann, rostedt, bsegall,
mgorman, vschneid, kprateek.nayak, linux-kernel
On 7/7/2026 12:03 AM, Vincent Guittot wrote:
> On Fri, 3 Jul 2026 at 11:50, Chen Jinghuang <chenjinghuang2@huawei.com> wrote:
>>
>> While running EEVDF-related test cases, we observed an anomalous
>> phenomenon where the vruntime of a continuously running scheduling
>> entity (se) exhibits an overall downward trend.
>>
>> The test topology and observed behavior are as follows:
>>
>> CPU 0 CPU 1 / Other CPUs
>> +----------------------------+ +----------------------------+
>> | cgroup A cgroup B | | cgroup A cgroup B |
>> | |- A1 (Run) |- B1 | | |- A2, A3... |- B2, B3...|
>> | (50us S)| | (Frequent sleep/wake) |
>> | (10us W)| | |
>> +----------------------------+ +----------------------------+
>> |
>> v
>> A2/A3 frequent sleep/wake -> Frequent reweight of gse(A) on CPU 0
>> -> Triggers vlag clamping -> Unidirectional avruntime drift
>> -> gse->vruntime drops abnormally (while gse weight remains stable)
>>
>> According to function_graph traces, frequent sleep/wake cycles of
>> sibling tasks within the same cgroup cause the running task to repeatedly
>> trigger update_cfs_cgroup() -> reweight_entity().
>>
>> The root cause appears to point to the entity_lag() boundary limit
>> introduced in `reweight_entity()` to prevent overflows. During repeated
>> weight scaling, this limit introduces an asymmetric cumulative error.
>> Connsider an example here where se->vruntime > avruntime:
>>
>> 1. Downscale:
>> se->vlag = entity_lag(cfs_rq, se, avruntime);
>
> The clamp applied in entity_lag() should "in theory never" happen.
>
However, I observed that vlag does indeed get clamped in entity_lag() on
CPU 0 in the test case
> Do you have more details to share about your setup?
>
Here is the exact layout of the cgroups:
- cgroup A: Besides task A1 (which is bound to CPU 0), there are 20 other
tasks running on the remaining CPUs (excluding CPU 0) that frequently
sleep and wake up. This setup is designed to continuously trigger weight
adjustments for A1.
- cgroup B: There is only a single task B1 bound to CPU 0, which sleeps for
long periods and wakes up briefly to compete with A1.(Please note that my
previous diagram mistakenly showed other tasks running under cgroup B on
other CPUs; that was an error on my part).
> Which kernel version do you use ? A number of changes have been queued
> recently that should ensure that the vlag never goes above the
> theoretical limit.
>
I am running the mainline kernel, specifically on the v7.2-rc2 tag.
> How many CPUs are in the system ?
> Is there other tasks running in the cgroups ?
>
The system has 32 CPUs in total.
> Could you try to run without RUN_TO_PARITY ?
> echo NO_RUN_TO_PARITY > /sys/kernel/debug/sched/features
>
I tried disabling RUN_TO_PARITY, but the issue persists—vlag
still exceeds the limit and triggers the clamp.
> Do you set the share of task groups to particular values?
> Do you change the slice of the tasks ?
>
No, I haven't set specific shares for the task groups (they are all at the
default value of 1024), nor have I modified the default task slices.
> Note that even without clamping, part of the vlag is lost in div64_long
>
>> se->vlag = div64_long(se->vlag * old_weight, weight);
>> se->vruntime = avruntime - se->vlag;
>>
>> If the calculated vlag exceeds the limit boundary, it is clamped.
>> This causes the scaled vlag to be bigger than its theoretical value,
>> making the resulting se->vruntime smaller than it should be (forced
>> closer to avruntime).
>>
>> 2. Upscale:
>> Because se->vruntime already carries the clamping error from the
>> previous step, it implicitly shifts the subsequent global avruntime
>> computation trajectory. When the weight is restored, se->vruntime
>> deviates from its original true value, preventing the true vlag from
>> being reconstructed and leading to a unidirectional avruntime drift.
>>
>> Under frequent cgroup reweighting, this asymmetric truncation error
>> accumulates, causing a unidirectional downward drift of vruntime.
>>
>> Regarding this vlag limit mechanism in reweight_entity(), we would like
>> to raise a few questions for discussion:
>>
>> Question 1: Is this deviation of se->vruntime expected?
>> For a currently running entity (curr se), due to RUN_TO_PARITY, it
>> typically operates in a state where se->vruntime > avruntime. During
>> reweighting, the limit forces its vruntime downward (closer to avruntime),
>> while attributes like deadline remain unaffected by the limit.
>>
>> Question 2: Is the unidirectional drift of avruntime reasonable?
>> Since avruntime = avg_vruntime(), the deviation of se->vruntime
>> before and after reweighting (while its weight remains unchanged) shifts
>> the global avruntime downward. According to EEVDF core principles,
>> avruntime should remain invariant across weight changes.
>> (https://lore.kernel.org/lkml/20260415211149.2658910-1-jstultz@google.com/),
>>
>> Question 3: Is the reduction of avruntime fair to other entities?
>> A non-functional reduction in global avruntime passively decreases the
>> se->vlag of other queued entities on the runqueue, which practically
>> worsens the starvation of those tasks.
>>
>> Question 4: Does this lead to complete preemption suppression?
>> In entity_tick -> update_deadline, because curr->vruntime is abnormally
>> pulled down by the clamping error while its deadline is unchanged, the
>> condition vruntime < deadline can be continuously satisfied at every
>> tick. This skips resched_curr(), suppressing preemption until the
>> frequent reweighting stops or curr's vlag falls back within the limit.
>>
>> While entity_lag() was originally introduced to prevent overflow-induced
>> NULL pointer dereferences, given its significant impact on EEVDF fairness,
>> should the necessity and implementation of this limit be reconsidered?
>>
>> Analyzed-by: Hui Tang <tanghui20@huawei.com>
>> Analyzed-by: Zhang Qiao <zhangqiao22@huawei.com>
>> Analyzed-by: Zicheng Qu <quzicheng@huawei.com>
>> Analyzed-by: Chen Jinghuang <chenjinghuang2@huawei.com>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag()
2026-07-07 12:51 ` chenjinghuang
@ 2026-07-07 14:52 ` Vincent Guittot
2026-07-07 16:35 ` Vincent Guittot
0 siblings, 1 reply; 5+ messages in thread
From: Vincent Guittot @ 2026-07-07 14:52 UTC (permalink / raw)
To: chenjinghuang
Cc: mingo, peterz, juri.lelli, dietmar.eggemann, rostedt, bsegall,
mgorman, vschneid, kprateek.nayak, linux-kernel
On Tue, 7 Jul 2026 at 14:51, chenjinghuang <chenjinghuang2@huawei.com> wrote:
>
> On 7/7/2026 12:03 AM, Vincent Guittot wrote:
> > On Fri, 3 Jul 2026 at 11:50, Chen Jinghuang <chenjinghuang2@huawei.com> wrote:
> >>
> >> While running EEVDF-related test cases, we observed an anomalous
> >> phenomenon where the vruntime of a continuously running scheduling
> >> entity (se) exhibits an overall downward trend.
> >>
> >> The test topology and observed behavior are as follows:
> >>
> >> CPU 0 CPU 1 / Other CPUs
> >> +----------------------------+ +----------------------------+
> >> | cgroup A cgroup B | | cgroup A cgroup B |
> >> | |- A1 (Run) |- B1 | | |- A2, A3... |- B2, B3...|
> >> | (50us S)| | (Frequent sleep/wake) |
> >> | (10us W)| | |
> >> +----------------------------+ +----------------------------+
> >> |
> >> v
> >> A2/A3 frequent sleep/wake -> Frequent reweight of gse(A) on CPU 0
> >> -> Triggers vlag clamping -> Unidirectional avruntime drift
> >> -> gse->vruntime drops abnormally (while gse weight remains stable)
> >>
> >> According to function_graph traces, frequent sleep/wake cycles of
> >> sibling tasks within the same cgroup cause the running task to repeatedly
> >> trigger update_cfs_cgroup() -> reweight_entity().
> >>
> >> The root cause appears to point to the entity_lag() boundary limit
> >> introduced in `reweight_entity()` to prevent overflows. During repeated
> >> weight scaling, this limit introduces an asymmetric cumulative error.
> >> Connsider an example here where se->vruntime > avruntime:
> >>
> >> 1. Downscale:
> >> se->vlag = entity_lag(cfs_rq, se, avruntime);
> >
> > The clamp applied in entity_lag() should "in theory never" happen.
> >
>
> However, I observed that vlag does indeed get clamped in entity_lag() on
> CPU 0 in the test case
Ok, we have to understand why the lag exceeds the slice duration
>
> > Do you have more details to share about your setup?
> >
>
> Here is the exact layout of the cgroups:
> - cgroup A: Besides task A1 (which is bound to CPU 0), there are 20 other
> tasks running on the remaining CPUs (excluding CPU 0) that frequently
> sleep and wake up. This setup is designed to continuously trigger weight
> adjustments for A1.
> - cgroup B: There is only a single task B1 bound to CPU 0, which sleeps for
> long periods and wakes up briefly to compete with A1.(Please note that my
> previous diagram mistakenly showed other tasks running under cgroup B on
> other CPUs; that was an error on my part).
>
> > Which kernel version do you use ? A number of changes have been queued
> > recently that should ensure that the vlag never goes above the
> > theoretical limit.
> >
>
> I am running the mainline kernel, specifically on the v7.2-rc2 tag.
Thanks, I will try to reproduce it.
There are a number of additional patches in tip/sched/core that target
shorter slice preemption but also ensure that the lag of other tasks
"never" goes above the limit.
>
> > How many CPUs are in the system ?
> > Is there other tasks running in the cgroups ?
> >
>
> The system has 32 CPUs in total.
>
> > Could you try to run without RUN_TO_PARITY ?
> > echo NO_RUN_TO_PARITY > /sys/kernel/debug/sched/features
> >
>
> I tried disabling RUN_TO_PARITY, but the issue persists—vlag
> still exceeds the limit and triggers the clamp.
This is even weirder because the protection is only 700us compared
with a default slice of 2.8ms
>
> > Do you set the share of task groups to particular values?
> > Do you change the slice of the tasks ?
> >
>
> No, I haven't set specific shares for the task groups (they are all at the
> default value of 1024), nor have I modified the default task slices.
Thanks for the details
>
> > Note that even without clamping, part of the vlag is lost in div64_long
> >
> >> se->vlag = div64_long(se->vlag * old_weight, weight);
> >> se->vruntime = avruntime - se->vlag;
> >>
> >> If the calculated vlag exceeds the limit boundary, it is clamped.
> >> This causes the scaled vlag to be bigger than its theoretical value,
> >> making the resulting se->vruntime smaller than it should be (forced
> >> closer to avruntime).
> >>
> >> 2. Upscale:
> >> Because se->vruntime already carries the clamping error from the
> >> previous step, it implicitly shifts the subsequent global avruntime
> >> computation trajectory. When the weight is restored, se->vruntime
> >> deviates from its original true value, preventing the true vlag from
> >> being reconstructed and leading to a unidirectional avruntime drift.
> >>
> >> Under frequent cgroup reweighting, this asymmetric truncation error
> >> accumulates, causing a unidirectional downward drift of vruntime.
> >>
> >> Regarding this vlag limit mechanism in reweight_entity(), we would like
> >> to raise a few questions for discussion:
> >>
> >> Question 1: Is this deviation of se->vruntime expected?
> >> For a currently running entity (curr se), due to RUN_TO_PARITY, it
> >> typically operates in a state where se->vruntime > avruntime. During
> >> reweighting, the limit forces its vruntime downward (closer to avruntime),
> >> while attributes like deadline remain unaffected by the limit.
> >>
> >> Question 2: Is the unidirectional drift of avruntime reasonable?
> >> Since avruntime = avg_vruntime(), the deviation of se->vruntime
> >> before and after reweighting (while its weight remains unchanged) shifts
> >> the global avruntime downward. According to EEVDF core principles,
> >> avruntime should remain invariant across weight changes.
> >> (https://lore.kernel.org/lkml/20260415211149.2658910-1-jstultz@google.com/),
> >>
> >> Question 3: Is the reduction of avruntime fair to other entities?
> >> A non-functional reduction in global avruntime passively decreases the
> >> se->vlag of other queued entities on the runqueue, which practically
> >> worsens the starvation of those tasks.
> >>
> >> Question 4: Does this lead to complete preemption suppression?
> >> In entity_tick -> update_deadline, because curr->vruntime is abnormally
> >> pulled down by the clamping error while its deadline is unchanged, the
> >> condition vruntime < deadline can be continuously satisfied at every
> >> tick. This skips resched_curr(), suppressing preemption until the
> >> frequent reweighting stops or curr's vlag falls back within the limit.
> >>
> >> While entity_lag() was originally introduced to prevent overflow-induced
> >> NULL pointer dereferences, given its significant impact on EEVDF fairness,
> >> should the necessity and implementation of this limit be reconsidered?
> >>
> >> Analyzed-by: Hui Tang <tanghui20@huawei.com>
> >> Analyzed-by: Zhang Qiao <zhangqiao22@huawei.com>
> >> Analyzed-by: Zicheng Qu <quzicheng@huawei.com>
> >> Analyzed-by: Chen Jinghuang <chenjinghuang2@huawei.com>
> >
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag()
2026-07-07 14:52 ` Vincent Guittot
@ 2026-07-07 16:35 ` Vincent Guittot
0 siblings, 0 replies; 5+ messages in thread
From: Vincent Guittot @ 2026-07-07 16:35 UTC (permalink / raw)
To: chenjinghuang
Cc: mingo, peterz, juri.lelli, dietmar.eggemann, rostedt, bsegall,
mgorman, vschneid, kprateek.nayak, linux-kernel
On Tue, 7 Jul 2026 at 16:52, Vincent Guittot <vincent.guittot@linaro.org> wrote:
>
> On Tue, 7 Jul 2026 at 14:51, chenjinghuang <chenjinghuang2@huawei.com> wrote:
> >
> > On 7/7/2026 12:03 AM, Vincent Guittot wrote:
> > > On Fri, 3 Jul 2026 at 11:50, Chen Jinghuang <chenjinghuang2@huawei.com> wrote:
> > >>
> > >> While running EEVDF-related test cases, we observed an anomalous
> > >> phenomenon where the vruntime of a continuously running scheduling
> > >> entity (se) exhibits an overall downward trend.
> > >>
> > >> The test topology and observed behavior are as follows:
> > >>
> > >> CPU 0 CPU 1 / Other CPUs
> > >> +----------------------------+ +----------------------------+
> > >> | cgroup A cgroup B | | cgroup A cgroup B |
> > >> | |- A1 (Run) |- B1 | | |- A2, A3... |- B2, B3...|
> > >> | (50us S)| | (Frequent sleep/wake) |
> > >> | (10us W)| | |
> > >> +----------------------------+ +----------------------------+
> > >> |
> > >> v
> > >> A2/A3 frequent sleep/wake -> Frequent reweight of gse(A) on CPU 0
> > >> -> Triggers vlag clamping -> Unidirectional avruntime drift
> > >> -> gse->vruntime drops abnormally (while gse weight remains stable)
> > >>
> > >> According to function_graph traces, frequent sleep/wake cycles of
> > >> sibling tasks within the same cgroup cause the running task to repeatedly
> > >> trigger update_cfs_cgroup() -> reweight_entity().
> > >>
> > >> The root cause appears to point to the entity_lag() boundary limit
> > >> introduced in `reweight_entity()` to prevent overflows. During repeated
> > >> weight scaling, this limit introduces an asymmetric cumulative error.
> > >> Connsider an example here where se->vruntime > avruntime:
> > >>
> > >> 1. Downscale:
> > >> se->vlag = entity_lag(cfs_rq, se, avruntime);
> > >
> > > The clamp applied in entity_lag() should "in theory never" happen.
> > >
> >
> > However, I observed that vlag does indeed get clamped in entity_lag() on
> > CPU 0 in the test case
>
> Ok, we have to understand why the lag exceeds the slice duration
>
> >
> > > Do you have more details to share about your setup?
> > >
> >
> > Here is the exact layout of the cgroups:
> > - cgroup A: Besides task A1 (which is bound to CPU 0), there are 20 other
> > tasks running on the remaining CPUs (excluding CPU 0) that frequently
> > sleep and wake up. This setup is designed to continuously trigger weight
> > adjustments for A1.
> > - cgroup B: There is only a single task B1 bound to CPU 0, which sleeps for
> > long periods and wakes up briefly to compete with A1.(Please note that my
If task B1 sleeps for long periods and wakes up briefly, the vlag of
gse(A) is null most of the time and will hardly ever exceed the clamp
value. I can see gse(A) reweight on CPU0 but vlag is 0 most of the
time.
If I increase the runtime of task B1, I see some negative vlag values
for gse(A) but never values outside the clamp. How do you check that
vlag is outside the clamp value ?
I will continue trying to reproduce your problem, but I'm probably
missing something in the setup.
> > previous diagram mistakenly showed other tasks running under cgroup B on
> > other CPUs; that was an error on my part).
> >
> > > Which kernel version do you use ? A number of changes have been queued
> > > recently that should ensure that the vlag never goes above the
> > > theoretical limit.
> > >
> >
> > I am running the mainline kernel, specifically on the v7.2-rc2 tag.
>
> Thanks, I will try to reproduce it.
> There are a number of additional patches in tip/sched/core that target
> shorter slice preemption but also ensure that the lag of other tasks
> "never" goes above the limit.
>
> >
> > > How many CPUs are in the system ?
> > > Is there other tasks running in the cgroups ?
> > >
> >
> > The system has 32 CPUs in total.
> >
> > > Could you try to run without RUN_TO_PARITY ?
> > > echo NO_RUN_TO_PARITY > /sys/kernel/debug/sched/features
> > >
> >
> > I tried disabling RUN_TO_PARITY, but the issue persists—vlag
> > still exceeds the limit and triggers the clamp.
>
> This is even weirder because the protection is only 700us compared
> with a default slice of 2.8ms
>
> >
> > > Do you set the share of task groups to particular values?
> > > Do you change the slice of the tasks ?
> > >
> >
> > No, I haven't set specific shares for the task groups (they are all at the
> > default value of 1024), nor have I modified the default task slices.
>
> Thanks for the details
>
> >
> > > Note that even without clamping, part of the vlag is lost in div64_long
> > >
> > >> se->vlag = div64_long(se->vlag * old_weight, weight);
> > >> se->vruntime = avruntime - se->vlag;
> > >>
> > >> If the calculated vlag exceeds the limit boundary, it is clamped.
> > >> This causes the scaled vlag to be bigger than its theoretical value,
> > >> making the resulting se->vruntime smaller than it should be (forced
> > >> closer to avruntime).
> > >>
> > >> 2. Upscale:
> > >> Because se->vruntime already carries the clamping error from the
> > >> previous step, it implicitly shifts the subsequent global avruntime
> > >> computation trajectory. When the weight is restored, se->vruntime
> > >> deviates from its original true value, preventing the true vlag from
> > >> being reconstructed and leading to a unidirectional avruntime drift.
> > >>
> > >> Under frequent cgroup reweighting, this asymmetric truncation error
> > >> accumulates, causing a unidirectional downward drift of vruntime.
> > >>
> > >> Regarding this vlag limit mechanism in reweight_entity(), we would like
> > >> to raise a few questions for discussion:
> > >>
> > >> Question 1: Is this deviation of se->vruntime expected?
> > >> For a currently running entity (curr se), due to RUN_TO_PARITY, it
> > >> typically operates in a state where se->vruntime > avruntime. During
> > >> reweighting, the limit forces its vruntime downward (closer to avruntime),
> > >> while attributes like deadline remain unaffected by the limit.
> > >>
> > >> Question 2: Is the unidirectional drift of avruntime reasonable?
> > >> Since avruntime = avg_vruntime(), the deviation of se->vruntime
> > >> before and after reweighting (while its weight remains unchanged) shifts
> > >> the global avruntime downward. According to EEVDF core principles,
> > >> avruntime should remain invariant across weight changes.
> > >> (https://lore.kernel.org/lkml/20260415211149.2658910-1-jstultz@google.com/),
> > >>
> > >> Question 3: Is the reduction of avruntime fair to other entities?
> > >> A non-functional reduction in global avruntime passively decreases the
> > >> se->vlag of other queued entities on the runqueue, which practically
> > >> worsens the starvation of those tasks.
> > >>
> > >> Question 4: Does this lead to complete preemption suppression?
> > >> In entity_tick -> update_deadline, because curr->vruntime is abnormally
> > >> pulled down by the clamping error while its deadline is unchanged, the
> > >> condition vruntime < deadline can be continuously satisfied at every
> > >> tick. This skips resched_curr(), suppressing preemption until the
> > >> frequent reweighting stops or curr's vlag falls back within the limit.
> > >>
> > >> While entity_lag() was originally introduced to prevent overflow-induced
> > >> NULL pointer dereferences, given its significant impact on EEVDF fairness,
> > >> should the necessity and implementation of this limit be reconsidered?
> > >>
> > >> Analyzed-by: Hui Tang <tanghui20@huawei.com>
> > >> Analyzed-by: Zhang Qiao <zhangqiao22@huawei.com>
> > >> Analyzed-by: Zicheng Qu <quzicheng@huawei.com>
> > >> Analyzed-by: Chen Jinghuang <chenjinghuang2@huawei.com>
> > >
> >
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-07 16:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-03 9:26 [RFC PATCH] sched/fair: Address avruntime drift caused by entity_lag() Chen Jinghuang
2026-07-06 16:03 ` Vincent Guittot
2026-07-07 12:51 ` chenjinghuang
2026-07-07 14:52 ` Vincent Guittot
2026-07-07 16:35 ` Vincent Guittot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®