diff options
| author | Srivatsa Vaddagiri <vatsa@codeaurora.org> | 2013-12-12 17:06:11 -0800 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 19:58:38 -0700 |
| commit | 97ae7bae2cb823be587d85f3421ade6033f6f366 (patch) | |
| tree | dc2320975479d6a8370d4876ad4e299c6f846e62 | |
| parent | 5f10bd75eb0ef27794e28674c3b72865d846c385 (diff) | |
sched: Make scheduler aware of cpu frequency state
Capacity of a cpu (how much performance it can deliver) is partly
determined by its frequency (P) state, both current frequency as well
as max frequency it can reach. Knowing frequency state of cpus will
help scheduler optimize various functions such as tracking every
task's cpu demand and placing tasks on various cpus.
This patch has scheduler registering for cpufreq notifications to
become aware of cpu's frequency state. Subsequent patches will make
use of derived information for various purposes, such as task's scaled
load (cpu demand) accounting and task placement.
Change-Id: I376dffa1e7f3f47d0496cd7e6ef8b5642ab79016
Signed-off-by: Srivatsa Vaddagiri <vatsa@codeaurora.org>
[joonwoop@codeaurora.org: fixed minor conflict in kernel/sched/core.c.]
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
| -rw-r--r-- | kernel/sched/core.c | 67 | ||||
| -rw-r--r-- | kernel/sched/sched.h | 2 |
2 files changed, 69 insertions, 0 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e6bc81b37369..9a53673cd810 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -74,6 +74,7 @@ #include <linux/binfmts.h> #include <linux/context_tracking.h> #include <linux/compiler.h> +#include <linux/cpufreq.h> #include <asm/switch_to.h> #include <asm/tlb.h> @@ -286,6 +287,12 @@ __read_mostly int scheduler_running; */ int sysctl_sched_rt_runtime = 950000; +/* + * Maximum possible frequency across all cpus. Task demand and cpu + * capacity (cpu_power) metrics could be scaled in reference to it. + */ +static unsigned int max_possible_freq = 1; + /* cpus with isolated domains */ cpumask_var_t cpu_isolated_map; @@ -7389,6 +7396,63 @@ void __init sched_init_smp(void) } #endif /* CONFIG_SMP */ +static int cpufreq_notifier_policy(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_policy *policy = (struct cpufreq_policy *)data; + int i; + + if (val != CPUFREQ_NOTIFY) + return 0; + + for_each_cpu(i, policy->related_cpus) { + cpu_rq(i)->min_freq = policy->min; + cpu_rq(i)->max_freq = policy->max; + } + + max_possible_freq = max(max_possible_freq, policy->cpuinfo.max_freq); + + return 0; +} + +static int cpufreq_notifier_trans(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = (struct cpufreq_freqs *)data; + unsigned int cpu = freq->cpu, new_freq = freq->new; + + if (val != CPUFREQ_POSTCHANGE) + return 0; + + cpu_rq(cpu)->cur_freq = new_freq; + + return 0; +} + +static struct notifier_block notifier_policy_block = { + .notifier_call = cpufreq_notifier_policy +}; + +static struct notifier_block notifier_trans_block = { + .notifier_call = cpufreq_notifier_trans +}; + +static int register_sched_callback(void) +{ + int ret; + + ret = cpufreq_register_notifier(¬ifier_policy_block, + CPUFREQ_POLICY_NOTIFIER); + + if (!ret) + ret = cpufreq_register_notifier(¬ifier_trans_block, + CPUFREQ_TRANSITION_NOTIFIER); + + return 0; +} + +core_initcall(register_sched_callback); + int in_sched_functions(unsigned long addr) { return in_lock_functions(addr) || @@ -7526,6 +7590,9 @@ void __init sched_init(void) rq->online = 0; rq->idle_stamp = 0; rq->avg_idle = 2*sysctl_sched_migration_cost; + rq->cur_freq = 0; + rq->max_freq = 0; + rq->min_freq = 0; rq->max_idle_balance_cost = sysctl_sched_migration_cost; rq->cstate = 0; rq->wakeup_latency = 0; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index fffe2623477a..4061d3f9d93d 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -643,6 +643,8 @@ struct rq { u64 max_idle_balance_cost; #endif + int cur_freq, max_freq, min_freq; + #ifdef CONFIG_IRQ_TIME_ACCOUNTING u64 prev_irq_time; #endif |
