summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunjie Wu <junjiew@codeaurora.org>2015-05-26 17:54:38 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:03:24 -0700
commite5e613be759829935ef7ae26324d3aea64a087b3 (patch)
tree40a2860b950ce7dd4581144f271fd84f348d8b93
parent7ebf7c3881f22f25ed64724c06d44d5142b3912b (diff)
cpufreq: interactive: Use sched_get_cpus_busy() to query busy time
sched_get_cpus_busy() provides a snapshot of all CPUs' busy time information for the set of CPUs being queried. This avoids race condition due to migration when CPU load is queried one by one. Change-Id: I6afdfa74ff9f3ef616872df4e2c3bb04f6233c3f Signed-off-by: Junjie Wu <junjiew@codeaurora.org>
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 31151f0df5b1..7a262974b128 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -52,6 +52,7 @@ struct cpufreq_interactive_policyinfo {
bool reject_notification;
int governor_enabled;
struct cpufreq_interactive_tunables *cached_tunables;
+ unsigned long *cpu_busy_times;
};
/* Protected by per-policy load_lock */
@@ -442,7 +443,7 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
unsigned int index;
unsigned long flags;
unsigned long max_cpu;
- int i;
+ int i, fcpu;
struct cpufreq_govinfo govinfo;
if (!down_read_trylock(&ppol->enable_sem))
@@ -450,16 +451,20 @@ static void __cpufreq_interactive_timer(unsigned long data, bool is_notif)
if (!ppol->governor_enabled)
goto exit;
+ fcpu = cpumask_first(ppol->policy->related_cpus);
now = ktime_to_us(ktime_get());
spin_lock_irqsave(&ppol->load_lock, flags);
ppol->last_evaluated_jiffy = get_jiffies_64();
+ if (tunables->use_sched_load)
+ sched_get_cpus_busy(ppol->cpu_busy_times,
+ ppol->policy->related_cpus);
max_cpu = cpumask_first(ppol->policy->cpus);
for_each_cpu(i, ppol->policy->cpus) {
pcpu = &per_cpu(cpuinfo, i);
if (tunables->use_sched_load) {
- cputime_speedadj = (u64)sched_get_busy(i) *
- ppol->policy->cpuinfo.max_freq;
+ cputime_speedadj = (u64)ppol->cpu_busy_times[i - fcpu]
+ * ppol->policy->cpuinfo.max_freq;
do_div(cputime_speedadj, tunables->timer_rate);
} else {
now = update_load(i);
@@ -1467,6 +1472,7 @@ static struct cpufreq_interactive_policyinfo *get_policyinfo(
struct cpufreq_interactive_policyinfo *ppol =
per_cpu(polinfo, policy->cpu);
int i;
+ unsigned long *busy;
/* polinfo already allocated for policy, return */
if (ppol)
@@ -1476,6 +1482,14 @@ static struct cpufreq_interactive_policyinfo *get_policyinfo(
if (!ppol)
return ERR_PTR(-ENOMEM);
+ busy = kcalloc(cpumask_weight(policy->related_cpus), sizeof(*busy),
+ GFP_KERNEL);
+ if (!busy) {
+ kfree(ppol);
+ return ERR_PTR(-ENOMEM);
+ }
+ ppol->cpu_busy_times = busy;
+
init_timer_deferrable(&ppol->policy_timer);
ppol->policy_timer.function = cpufreq_interactive_timer;
init_timer(&ppol->policy_slack_timer);
@@ -1502,6 +1516,7 @@ static void free_policyinfo(int cpu)
if (per_cpu(polinfo, j) == ppol)
per_cpu(polinfo, cpu) = NULL;
kfree(ppol->cached_tunables);
+ kfree(ppol->cpu_busy_times);
kfree(ppol);
}