Skip to content

Commit 650cad5

Browse files
author
Peter Zijlstra
committed
sched/eevdf: Fix avg_vruntime()
The expectation is that placing a task at avg_vruntime() makes it eligible. Turns out there is a corner case where this is not the case. Specifically, avg_vruntime() relies on the fact that integer division is a flooring function (eg. it discards the remainder). By this property the value returned is slightly left of the true average. However! when the average is a negative (relative to min_vruntime) the effect is flipped and it becomes a ceil, with the result that the returned value is just right of the average and thus not eligible. Fixes: af4cf40 ("sched/fair: Add cfs_rq::avg_vruntime") Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
1 parent 2f2fc17 commit 650cad5

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

kernel/sched/fair.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,10 @@ void avg_vruntime_update(struct cfs_rq *cfs_rq, s64 delta)
664664
cfs_rq->avg_vruntime -= cfs_rq->avg_load * delta;
665665
}
666666

667+
/*
668+
* Specifically: avg_runtime() + 0 must result in entity_eligible() := true
669+
* For this to be so, the result of this function must have a left bias.
670+
*/
667671
u64 avg_vruntime(struct cfs_rq *cfs_rq)
668672
{
669673
struct sched_entity *curr = cfs_rq->curr;
@@ -677,8 +681,12 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
677681
load += weight;
678682
}
679683

680-
if (load)
684+
if (load) {
685+
/* sign flips effective floor / ceil */
686+
if (avg < 0)
687+
avg -= (load - 1);
681688
avg = div_s64(avg, load);
689+
}
682690

683691
return cfs_rq->min_vruntime + avg;
684692
}

0 commit comments

Comments
 (0)