Skip to content

Commit ac8e69e

Browse files
vingu-linaroPeter Zijlstra
authored andcommitted
sched/fair: Fix wakeup_preempt_fair() vs delayed dequeue
Similar to how pick_next_entity() must dequeue delayed entities, so too must wakeup_preempt_fair(). Any delayed task being found means it is eligible and hence past the 0-lag point, ready for removal. Worse, by not removing delayed entities from consideration, it can skew the preemption decision, with the end result that a short slice wakeup will not result in a preemption. tip/sched/core tip/sched/core +this patch cyclictest slice (ms) (default)2.8 8 8 hackbench slice (ms) (default)2.8 20 20 Total Samples | 22559 22595 22683 Average (us) | 157 64( 59%) 59( 8%) Median (P50) (us) | 57 57( 0%) 58(- 2%) 90th Percentile (us) | 64 60( 6%) 60( 0%) 99th Percentile (us) | 2407 67( 97%) 67( 0%) 99.9th Percentile (us) | 3400 2288( 33%) 727( 68%) Maximum (us) | 5037 9252(-84%) 7461( 19%) Fixes: f12e148 ("sched/fair: Prepare pick_next_task() for delayed dequeue") Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20260422093400.319251-1-vincent.guittot@linaro.org
1 parent c5cd6fd commit ac8e69e

1 file changed

Lines changed: 14 additions & 13 deletions

File tree

kernel/sched/fair.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,7 @@ static inline void cancel_protect_slice(struct sched_entity *se)
11041104
*
11051105
* Which allows tree pruning through eligibility.
11061106
*/
1107-
static struct sched_entity *__pick_eevdf(struct cfs_rq *cfs_rq, bool protect)
1107+
static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq, bool protect)
11081108
{
11091109
struct rb_node *node = cfs_rq->tasks_timeline.rb_root.rb_node;
11101110
struct sched_entity *se = __pick_first_entity(cfs_rq);
@@ -1175,11 +1175,6 @@ static struct sched_entity *__pick_eevdf(struct cfs_rq *cfs_rq, bool protect)
11751175
return best;
11761176
}
11771177

1178-
static struct sched_entity *pick_eevdf(struct cfs_rq *cfs_rq)
1179-
{
1180-
return __pick_eevdf(cfs_rq, true);
1181-
}
1182-
11831178
struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
11841179
{
11851180
struct rb_node *last = rb_last(&cfs_rq->tasks_timeline.rb_root);
@@ -5754,11 +5749,11 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags);
57545749
* 4) do not run the "skip" process, if something else is available
57555750
*/
57565751
static struct sched_entity *
5757-
pick_next_entity(struct rq *rq, struct cfs_rq *cfs_rq)
5752+
pick_next_entity(struct rq *rq, struct cfs_rq *cfs_rq, bool protect)
57585753
{
57595754
struct sched_entity *se;
57605755

5761-
se = pick_eevdf(cfs_rq);
5756+
se = pick_eevdf(cfs_rq, protect);
57625757
if (se->sched_delayed) {
57635758
dequeue_entities(rq, se, DEQUEUE_SLEEP | DEQUEUE_DELAYED);
57645759
/*
@@ -9032,7 +9027,7 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f
90329027
{
90339028
enum preempt_wakeup_action preempt_action = PREEMPT_WAKEUP_PICK;
90349029
struct task_struct *donor = rq->donor;
9035-
struct sched_entity *se = &donor->se, *pse = &p->se;
9030+
struct sched_entity *nse, *se = &donor->se, *pse = &p->se;
90369031
struct cfs_rq *cfs_rq = task_cfs_rq(donor);
90379032
int cse_is_idle, pse_is_idle;
90389033

@@ -9143,11 +9138,17 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f
91439138
}
91449139

91459140
pick:
9141+
nse = pick_next_entity(rq, cfs_rq, preempt_action != PREEMPT_WAKEUP_SHORT);
9142+
/* If @p has become the most eligible task, force preemption */
9143+
if (nse == pse)
9144+
goto preempt;
9145+
91469146
/*
9147-
* If @p has become the most eligible task, force preemption.
9147+
* Because p is enqueued, nse being null can only mean that we
9148+
* dequeued a delayed task.
91489149
*/
9149-
if (__pick_eevdf(cfs_rq, preempt_action != PREEMPT_WAKEUP_SHORT) == pse)
9150-
goto preempt;
9150+
if (!nse)
9151+
goto pick;
91519152

91529153
if (sched_feat(RUN_TO_PARITY))
91539154
update_protect_slice(cfs_rq, se);
@@ -9184,7 +9185,7 @@ static struct task_struct *pick_task_fair(struct rq *rq, struct rq_flags *rf)
91849185

91859186
throttled |= check_cfs_rq_runtime(cfs_rq);
91869187

9187-
se = pick_next_entity(rq, cfs_rq);
9188+
se = pick_next_entity(rq, cfs_rq, true);
91889189
if (!se)
91899190
goto again;
91909191
cfs_rq = group_cfs_rq(se);

0 commit comments

Comments
 (0)