From cc2c83709c5ca27548491d9b7a415c51e05e3600 Mon Sep 17 00:00:00 2001 From: Chris Redpath Date: Mon, 9 Jul 2018 16:54:02 +0100 Subject: [PATCH] ANDROID: sched/rt: Add schedtune accounting to rt task enqueue/dequeue rt tasks are currently not eligible for schedtune boosting. Make it so by adding enqueue/dequeue hooks. For rt tasks, schedtune only acts as a frequency boosting framework, it has no impact on placement decisions and the prefer_idle attribute is not used. Also prepare schedutil use of boosted util for rt task boosting With this change, schedtune accounting will include rt class tasks, however boosting currently only applies to the utilization provided by fair class tasks. Sum up the tracked CPU utilization applying boost to the aggregate util instead - this includes RT task util in the boosting if any tasks are runnable. Scenario 1, considering one CPU: 1x rt task running, util 250, boost 0 1x cfs task runnable, util 250, boost 50 previous util=250+(50pct_boosted_250) = 887 new util=50_pct_boosted_500 = 762 Scenario 2, considering one CPU: 1x rt task running, util 250, boost 50 1x cfs task runnable, util 250, boost 0 previous util=250+250 = 500 new util=50_pct_boosted_500 = 762 Scenario 3, considering one CPU: 1x rt task running, util 250, boost 50 1x cfs task runnable, util 250, boost 50 previous util=250+(50pct_boosted_250) = 887 new util=50_pct_boosted_500 = 762 Scenario 4: 1x rt task running, util 250, boost 50 previous util=250 = 250 new util=50_pct_boosted_250 = 637 Change-Id: Ie287cbd0692468525095b5024db9faac8b2f4878 Signed-off-by: Chris Redpath (cherry picked from commit 8e266aebf737262aeca9662254a3e61ccc7f8dec) [ - Fixed conflicts in sugov related to PELT signals of all classes - Fixed conflicts related to boosted_cpu_util being in a different location - Moved the CFS/RT util aggregation out of schedutil_freq_util to ease the integration with SchedTune ] Signed-off-by: Quentin Perret --- kernel/sched/cpufreq_schedutil.c | 21 ++++++++++----------- kernel/sched/fair.c | 7 +++---- kernel/sched/rt.c | 4 ++++ kernel/sched/sched.h | 10 +++++----- kernel/sched/tune.h | 4 ++-- 5 files changed, 24 insertions(+), 22 deletions(-) diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index b01cd99ffbd0..f1841ce4555f 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -219,6 +219,9 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, * Where the cfs,rt and dl util numbers are tracked with the same metric and * synchronized windows and are thus directly comparable. * + * The @util parameter passed to this function is assumed to be the aggregation + * of RT and CFS util numbers. The cases of DL and IRQ are managed here. + * * The cfs,rt,dl utilization are the running times measured with rq->clock_task * which excludes things like IRQ and steal-time. These latter are then accrued * in the irq utilization. @@ -227,11 +230,11 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, * based on the task model parameters and gives the minimal utilization * required to meet deadlines. */ -unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs, +unsigned long schedutil_freq_util(int cpu, unsigned long util, unsigned long max, enum schedutil_type type) { struct rq *rq = cpu_rq(cpu); - unsigned long util, irq; + unsigned long irq; if (sched_feat(SUGOV_RT_MAX_FREQ) && type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) @@ -247,14 +250,11 @@ unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs, return max; /* - * Because the time spend on RT/DL tasks is visible as 'lost' time to - * CFS tasks and we use the same metric to track the effective - * utilization (PELT windows are synchronized) we can directly add them - * to obtain the CPU's actual utilization. + * The function is called with @util defined as the aggregation (the + * sum) of RT and CFS signals, hence leaving the special case of DL + * to be delt with. The exact way of doing things depend on the calling + * context. */ - util = util_cfs; - util += cpu_util_rt(rq); - if (type == FREQUENCY_UTIL) { /* * For frequency selection we do not make cpu_util_dl() a @@ -267,7 +267,6 @@ unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs, * to not quite hit saturation when we should -- * something for later. */ - if ((util + cpu_util_dl(rq)) >= max) return max; } else { @@ -314,7 +313,7 @@ unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs, static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) { struct rq *rq = cpu_rq(sg_cpu->cpu); - unsigned long util = boosted_cpu_util(sg_cpu->cpu); + unsigned long util = boosted_cpu_util(sg_cpu->cpu, cpu_util_rt(rq)); unsigned long max = arch_scale_cpu_capacity(NULL, sg_cpu->cpu); sg_cpu->max = max; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 36d2f3bde904..8f3573d7165d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5849,9 +5849,9 @@ schedtune_task_margin(struct task_struct *task) } unsigned long -boosted_cpu_util(int cpu) +boosted_cpu_util(int cpu, unsigned long other_util) { - unsigned long util = cpu_util_cfs(cpu_rq(cpu)); + unsigned long util = cpu_util_cfs(cpu_rq(cpu)) + other_util; long margin = schedtune_cpu_margin(util, cpu); trace_sched_boost_cpu(cpu, util, margin); @@ -5875,8 +5875,6 @@ schedtune_task_margin(struct task_struct *task) #endif /* CONFIG_SCHED_TUNE */ - - static inline unsigned long boosted_task_util(struct task_struct *task) { @@ -6892,6 +6890,7 @@ compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd) */ for_each_cpu_and(cpu, perf_domain_span(pd), cpu_online_mask) { util = cpu_util_next(cpu, p, dst_cpu); + util += cpu_util_rt(cpu_rq(cpu)); util = schedutil_energy_util(cpu, util); max_util = max(util, max_util); sum_util += util; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 0be707d9c2db..3eed85fc86db 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1329,6 +1329,8 @@ enqueue_task_rt(struct rq *rq, struct task_struct *p, int flags) { struct sched_rt_entity *rt_se = &p->rt; + schedtune_enqueue_task(p, cpu_of(rq)); + if (flags & ENQUEUE_WAKEUP) rt_se->timeout = 0; @@ -1342,6 +1344,8 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int flags) { struct sched_rt_entity *rt_se = &p->rt; + schedtune_dequeue_task(p, cpu_of(rq)); + update_curr_rt(rq); dequeue_rt_entity(rt_se, flags); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 3997a6908afd..33911f3f74ac 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2253,19 +2253,19 @@ enum schedutil_type { ENERGY_UTIL, }; -unsigned long schedutil_freq_util(int cpu, unsigned long util_cfs, +unsigned long schedutil_freq_util(int cpu, unsigned long util, unsigned long max, enum schedutil_type type); -static inline unsigned long schedutil_energy_util(int cpu, unsigned long cfs) +static inline unsigned long schedutil_energy_util(int cpu, unsigned long util) { unsigned long max = arch_scale_cpu_capacity(NULL, cpu); - return schedutil_freq_util(cpu, cfs, max, ENERGY_UTIL); + return schedutil_freq_util(cpu, util, max, ENERGY_UTIL); } #else /* CONFIG_CPU_FREQ_GOV_SCHEDUTIL */ -static inline unsigned long schedutil_energy_util(int cpu, unsigned long cfs) +static inline unsigned long schedutil_energy_util(int cpu, unsigned long util) { - return cfs; + return util; } #endif diff --git a/kernel/sched/tune.h b/kernel/sched/tune.h index bb187c6112a7..821f026b510f 100644 --- a/kernel/sched/tune.h +++ b/kernel/sched/tune.h @@ -20,7 +20,7 @@ int schedtune_prefer_idle(struct task_struct *tsk); void schedtune_enqueue_task(struct task_struct *p, int cpu); void schedtune_dequeue_task(struct task_struct *p, int cpu); -unsigned long boosted_cpu_util(int cpu); +unsigned long boosted_cpu_util(int cpu, unsigned long other_util); #else /* CONFIG_SCHED_TUNE */ @@ -32,6 +32,6 @@ unsigned long boosted_cpu_util(int cpu); #define schedtune_enqueue_task(task, cpu) do { } while (0) #define schedtune_dequeue_task(task, cpu) do { } while (0) -#define boosted_cpu_util(cpu) cpu_util_cfs(cpu_rq(cpu)) +#define boosted_cpu_util(cpu, other_util) cpu_util_cfs(cpu_rq(cpu)) #endif /* CONFIG_SCHED_TUNE */