Skip to content

Commit dfa0a57

Browse files
author
Peter Zijlstra
committed
sched/uclamg: Handle delayed dequeue
Delayed dequeue has tasks sit around on the runqueue that are not actually runnable -- specifically, they will be dequeued the moment they get picked. One side-effect is that such a task can get migrated, which leads to a 'nested' dequeue_task() scenario that messes up uclamp if we don't take care. Notably, dequeue_task(DEQUEUE_SLEEP) can 'fail' and keep the task on the runqueue. This however will have removed the task from uclamp -- per uclamp_rq_dec() in dequeue_task(). So far so good. However, if at that point the task gets migrated -- or nice adjusted or any of a myriad of operations that does a dequeue-enqueue cycle -- we'll pass through dequeue_task()/enqueue_task() again. Without modification this will lead to a double decrement for uclamp, which is wrong. Reported-by: Luis Machado <[email protected]> Reported-by: Hongyan Xia <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> Tested-by: Valentin Schneider <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent abc158c commit dfa0a57

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

kernel/sched/core.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,9 @@ static inline void uclamp_rq_inc(struct rq *rq, struct task_struct *p)
16911691
if (unlikely(!p->sched_class->uclamp_enabled))
16921692
return;
16931693

1694+
if (p->se.sched_delayed)
1695+
return;
1696+
16941697
for_each_clamp_id(clamp_id)
16951698
uclamp_rq_inc_id(rq, p, clamp_id);
16961699

@@ -1715,6 +1718,9 @@ static inline void uclamp_rq_dec(struct rq *rq, struct task_struct *p)
17151718
if (unlikely(!p->sched_class->uclamp_enabled))
17161719
return;
17171720

1721+
if (p->se.sched_delayed)
1722+
return;
1723+
17181724
for_each_clamp_id(clamp_id)
17191725
uclamp_rq_dec_id(rq, p, clamp_id);
17201726
}
@@ -1994,8 +2000,12 @@ void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
19942000
psi_enqueue(p, (flags & ENQUEUE_WAKEUP) && !(flags & ENQUEUE_MIGRATED));
19952001
}
19962002

1997-
uclamp_rq_inc(rq, p);
19982003
p->sched_class->enqueue_task(rq, p, flags);
2004+
/*
2005+
* Must be after ->enqueue_task() because ENQUEUE_DELAYED can clear
2006+
* ->sched_delayed.
2007+
*/
2008+
uclamp_rq_inc(rq, p);
19992009

20002010
if (sched_core_enabled(rq))
20012011
sched_core_enqueue(rq, p);
@@ -2017,6 +2027,10 @@ inline bool dequeue_task(struct rq *rq, struct task_struct *p, int flags)
20172027
psi_dequeue(p, flags & DEQUEUE_SLEEP);
20182028
}
20192029

2030+
/*
2031+
* Must be before ->dequeue_task() because ->dequeue_task() can 'fail'
2032+
* and mark the task ->sched_delayed.
2033+
*/
20202034
uclamp_rq_dec(rq, p);
20212035
return p->sched_class->dequeue_task(rq, p, flags);
20222036
}

0 commit comments

Comments
 (0)