Skip to content

Commit 982d9cd

Browse files
derklingIngo Molnar
authored andcommitted
sched/cpufreq, sched/uclamp: Add clamps for FAIR and RT tasks
Each time a frequency update is required via schedutil, a frequency is selected to (possibly) satisfy the utilization reported by each scheduling class and irqs. However, when utilization clamping is in use, the frequency selection should consider userspace utilization clamping hints. This will allow, for example, to: - boost tasks which are directly affecting the user experience by running them at least at a minimum "requested" frequency - cap low priority tasks not directly affecting the user experience by running them only up to a maximum "allowed" frequency These constraints are meant to support a per-task based tuning of the frequency selection thus supporting a fine grained definition of performance boosting vs energy saving strategies in kernel space. Add support to clamp the utilization of RUNNABLE FAIR and RT tasks within the boundaries defined by their aggregated utilization clamp constraints. Do that by considering the max(min_util, max_util) to give boosted tasks the performance they need even when they happen to be co-scheduled with other capped tasks. Signed-off-by: Patrick Bellasi <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: Alessio Balsini <[email protected]> Cc: Dietmar Eggemann <[email protected]> Cc: Joel Fernandes <[email protected]> Cc: Juri Lelli <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Morten Rasmussen <[email protected]> Cc: Paul Turner <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Quentin Perret <[email protected]> Cc: Rafael J . Wysocki <[email protected]> Cc: Steve Muckle <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: Tejun Heo <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Todd Kjos <[email protected]> Cc: Vincent Guittot <[email protected]> Cc: Viresh Kumar <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 1a00d99 commit 982d9cd

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

kernel/sched/cpufreq_schedutil.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
202202
unsigned long dl_util, util, irq;
203203
struct rq *rq = cpu_rq(cpu);
204204

205-
if (type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt))
205+
if (!IS_BUILTIN(CONFIG_UCLAMP_TASK) &&
206+
type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
206207
return max;
208+
}
207209

208210
/*
209211
* Early check to see if IRQ/steal time saturates the CPU, can be
@@ -219,9 +221,16 @@ unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs,
219221
* CFS tasks and we use the same metric to track the effective
220222
* utilization (PELT windows are synchronized) we can directly add them
221223
* to obtain the CPU's actual utilization.
224+
*
225+
* CFS and RT utilization can be boosted or capped, depending on
226+
* utilization clamp constraints requested by currently RUNNABLE
227+
* tasks.
228+
* When there are no CFS RUNNABLE tasks, clamps are released and
229+
* frequency will be gracefully reduced with the utilization decay.
222230
*/
223-
util = util_cfs;
224-
util += cpu_util_rt(rq);
231+
util = util_cfs + cpu_util_rt(rq);
232+
if (type == FREQUENCY_UTIL)
233+
util = uclamp_util(rq, util);
225234

226235
dl_util = cpu_util_dl(rq);
227236

kernel/sched/fair.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10393,6 +10393,10 @@ const struct sched_class fair_sched_class = {
1039310393
#ifdef CONFIG_FAIR_GROUP_SCHED
1039410394
.task_change_group = task_change_group_fair,
1039510395
#endif
10396+
10397+
#ifdef CONFIG_UCLAMP_TASK
10398+
.uclamp_enabled = 1,
10399+
#endif
1039610400
};
1039710401

1039810402
#ifdef CONFIG_SCHED_DEBUG

kernel/sched/rt.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,10 @@ const struct sched_class rt_sched_class = {
24002400
.switched_to = switched_to_rt,
24012401

24022402
.update_curr = update_curr_rt,
2403+
2404+
#ifdef CONFIG_UCLAMP_TASK
2405+
.uclamp_enabled = 1,
2406+
#endif
24032407
};
24042408

24052409
#ifdef CONFIG_RT_GROUP_SCHED

kernel/sched/sched.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,29 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
22652265
static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {}
22662266
#endif /* CONFIG_CPU_FREQ */
22672267

2268+
#ifdef CONFIG_UCLAMP_TASK
2269+
static inline unsigned int uclamp_util(struct rq *rq, unsigned int util)
2270+
{
2271+
unsigned int min_util = READ_ONCE(rq->uclamp[UCLAMP_MIN].value);
2272+
unsigned int max_util = READ_ONCE(rq->uclamp[UCLAMP_MAX].value);
2273+
2274+
/*
2275+
* Since CPU's {min,max}_util clamps are MAX aggregated considering
2276+
* RUNNABLE tasks with _different_ clamps, we can end up with an
2277+
* inversion. Fix it now when the clamps are applied.
2278+
*/
2279+
if (unlikely(min_util >= max_util))
2280+
return min_util;
2281+
2282+
return clamp(util, min_util, max_util);
2283+
}
2284+
#else /* CONFIG_UCLAMP_TASK */
2285+
static inline unsigned int uclamp_util(struct rq *rq, unsigned int util)
2286+
{
2287+
return util;
2288+
}
2289+
#endif /* CONFIG_UCLAMP_TASK */
2290+
22682291
#ifdef arch_scale_freq_capacity
22692292
# ifndef arch_scale_freq_invariant
22702293
# define arch_scale_freq_invariant() true

0 commit comments

Comments
 (0)