aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJuri Lelli <juri.lelli@arm.com>2017-05-03 09:30:48 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-05-05 17:34:32 -0400
commitd86ab9cff8b936aadde444d0e263a8db5ff0349b (patch)
tree74524bf813b3b0605983dcb16f03b2231d43d981 /kernel
parent1b72e7fd304639f1cd49d1e11955c4974936d88c (diff)
cpufreq: schedutil: use now as reference when aggregating shared policy requests
Currently, sugov_next_freq_shared() uses last_freq_update_time as a reference to decide when to start considering CPU contributions as stale. However, since last_freq_update_time is set by the last CPU that issued a frequency transition, this might cause problems in certain cases. In practice, the detection of stale utilization values fails whenever the CPU with such values was the last to update the policy. For example (and please note again that the SCHED_CPUFREQ_RT flag is not the problem here, but only the detection of after how much time that flag has to be considered stale), suppose a policy with 2 CPUs: CPU0 | CPU1 | | RT task scheduled | SCHED_CPUFREQ_RT is set | CPU1->last_update = now | freq transition to max | last_freq_update_time = now | more than TICK_NSEC nsecs | a small CFS wakes up | CPU0->last_update = now1 | delta_ns(CPU0) < TICK_NSEC* | CPU0's util is considered | delta_ns(CPU1) = | last_freq_update_time - | CPU1->last_update = 0 | < TICK_NSEC | CPU1 is still considered | CPU1->SCHED_CPUFREQ_RT is set | we stay at max (until CPU1 | exits from idle) | * delta_ns is actually negative as now1 > last_freq_update_time While last_freq_update_time is a sensible reference for rate limiting, it doesn't seem to be useful for working around stale CPU states. Fix the problem by always considering now (time) as the reference for deciding when CPUs have stale contributions. Signed-off-by: Juri Lelli <juri.lelli@arm.com> Acked-by: Vincent Guittot <vincent.guittot@linaro.org> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/cpufreq_schedutil.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 76877a62b5fa..622eed1b7658 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -245,11 +245,10 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
245 sugov_update_commit(sg_policy, time, next_f); 245 sugov_update_commit(sg_policy, time, next_f);
246} 246}
247 247
248static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu) 248static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
249{ 249{
250 struct sugov_policy *sg_policy = sg_cpu->sg_policy; 250 struct sugov_policy *sg_policy = sg_cpu->sg_policy;
251 struct cpufreq_policy *policy = sg_policy->policy; 251 struct cpufreq_policy *policy = sg_policy->policy;
252 u64 last_freq_update_time = sg_policy->last_freq_update_time;
253 unsigned long util = 0, max = 1; 252 unsigned long util = 0, max = 1;
254 unsigned int j; 253 unsigned int j;
255 254
@@ -265,7 +264,7 @@ static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu)
265 * enough, don't take the CPU into account as it probably is 264 * enough, don't take the CPU into account as it probably is
266 * idle now (and clear iowait_boost for it). 265 * idle now (and clear iowait_boost for it).
267 */ 266 */
268 delta_ns = last_freq_update_time - j_sg_cpu->last_update; 267 delta_ns = time - j_sg_cpu->last_update;
269 if (delta_ns > TICK_NSEC) { 268 if (delta_ns > TICK_NSEC) {
270 j_sg_cpu->iowait_boost = 0; 269 j_sg_cpu->iowait_boost = 0;
271 continue; 270 continue;
@@ -309,7 +308,7 @@ static void sugov_update_shared(struct update_util_data *hook, u64 time,
309 if (flags & SCHED_CPUFREQ_RT_DL) 308 if (flags & SCHED_CPUFREQ_RT_DL)
310 next_f = sg_policy->policy->cpuinfo.max_freq; 309 next_f = sg_policy->policy->cpuinfo.max_freq;
311 else 310 else
312 next_f = sugov_next_freq_shared(sg_cpu); 311 next_f = sugov_next_freq_shared(sg_cpu, time);
313 312
314 sugov_update_commit(sg_policy, time, next_f); 313 sugov_update_commit(sg_policy, time, next_f);
315 } 314 }