Skip to content

Commit 3e1493f

Browse files
Xuewen YanPeter Zijlstra
authored andcommitted
sched/uclamp: Ignore max aggregation if rq is idle
When a task wakes up on an idle rq, uclamp_rq_util_with() would max aggregate with rq value. But since there is no task enqueued yet, the values are stale based on the last task that was running. When the new task actually wakes up and enqueued, then the rq uclamp values should reflect that of the newly woken up task effective uclamp values. This is a problem particularly for uclamp_max because it default to 1024. If a task p with uclamp_max = 512 wakes up, then max aggregation would ignore the capping that should apply when this task is enqueued, which is wrong. Fix that by ignoring max aggregation if the rq is idle since in that case the effective uclamp value of the rq will be the ones of the task that will wake up. Fixes: 9d20ad7 ("sched/uclamp: Add uclamp_util_with()") Signed-off-by: Xuewen Yan <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> [qias: Changelog] Reviewed-by: Qais Yousef <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 72d0ad7 commit 3e1493f

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

kernel/sched/sched.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2818,20 +2818,27 @@ static __always_inline
28182818
unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
28192819
struct task_struct *p)
28202820
{
2821-
unsigned long min_util;
2822-
unsigned long max_util;
2821+
unsigned long min_util = 0;
2822+
unsigned long max_util = 0;
28232823

28242824
if (!static_branch_likely(&sched_uclamp_used))
28252825
return util;
28262826

2827-
min_util = READ_ONCE(rq->uclamp[UCLAMP_MIN].value);
2828-
max_util = READ_ONCE(rq->uclamp[UCLAMP_MAX].value);
2829-
28302827
if (p) {
2831-
min_util = max(min_util, uclamp_eff_value(p, UCLAMP_MIN));
2832-
max_util = max(max_util, uclamp_eff_value(p, UCLAMP_MAX));
2828+
min_util = uclamp_eff_value(p, UCLAMP_MIN);
2829+
max_util = uclamp_eff_value(p, UCLAMP_MAX);
2830+
2831+
/*
2832+
* Ignore last runnable task's max clamp, as this task will
2833+
* reset it. Similarly, no need to read the rq's min clamp.
2834+
*/
2835+
if (rq->uclamp_flags & UCLAMP_FLAG_IDLE)
2836+
goto out;
28332837
}
28342838

2839+
min_util = max_t(unsigned long, min_util, READ_ONCE(rq->uclamp[UCLAMP_MIN].value));
2840+
max_util = max_t(unsigned long, max_util, READ_ONCE(rq->uclamp[UCLAMP_MAX].value));
2841+
out:
28352842
/*
28362843
* Since CPU's {min,max}_util clamps are MAX aggregated considering
28372844
* RUNNABLE tasks with _different_ clamps, we can end up with an

0 commit comments

Comments
 (0)