diff options
| author | Steve Muckle <smuckle@codeaurora.org> | 2014-03-25 14:34:41 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 19:59:24 -0700 |
| commit | 9931863046ec2ba6c79838e3b8bb0839b1104aa8 (patch) | |
| tree | efaec5a54f45d7a2fa5683bc3a3c4a8e4ed34393 | |
| parent | a31debf1c93cc87f60915e06d00889a8a047656e (diff) | |
sched: do nohz load balancing in order of power efficiency
The nohz load balancer CPU does load balancing on behalf of all
idle tickless CPUs. In the interest of power efficiency though, we
should do load balancing on the most power efficient idle tickless
CPU first, and then work our way towards the least power efficient
idle tickless CPU. This will help load find its way to the most
power efficient CPUs in the system.
Since when selecting the CPU to balance next it is unknown what
task load would be pulled, a frequency must be assumed in order
to do a comparison of CPU power consumption. The maximum
freqeuncy supported by all CPUs is used for this.
Change-Id: I96c7f4300fde2c677c068dc10fc0e57f763eb9b2
Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
Signed-off-by: Srivatsa Vaddagiri <vatsa@codeaurora.org>
[joonwoop@codeaurora.org: fixed minor conflict in nohz_idle_balance().]
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
| -rw-r--r-- | kernel/sched/fair.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 2cb70c88d18a..bb6704e0ee09 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -8532,6 +8532,28 @@ out: } #ifdef CONFIG_NO_HZ_COMMON + +static int select_lowest_power_cpu(struct cpumask *cpus) +{ + int i, cost; + int lowest_power_cpu = -1; + int lowest_power = INT_MAX; + + if (sysctl_sched_enable_power_aware) { + for_each_cpu(i, cpus) { + cost = power_cost_at_freq(i, 0); + if (cost < lowest_power) { + lowest_power_cpu = i; + lowest_power = cost; + } + } + BUG_ON(lowest_power_cpu == -1); + return lowest_power_cpu; + } else { + return cpumask_first(cpus); + } +} + /* * In CONFIG_NO_HZ_COMMON case, the idle balance kickee will do the * rebalancing for all the cpus for whom scheduler ticks are stopped. @@ -8544,12 +8566,18 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle) /* Earliest time when we have to do rebalance again */ unsigned long next_balance = jiffies + 60*HZ; int update_next_balance = 0; + struct cpumask cpus_to_balance; if (idle != CPU_IDLE || !test_bit(NOHZ_BALANCE_KICK, nohz_flags(this_cpu))) goto end; - for_each_cpu(balance_cpu, nohz.idle_cpus_mask) { + cpumask_copy(&cpus_to_balance, nohz.idle_cpus_mask); + + while (!cpumask_empty(&cpus_to_balance)) { + balance_cpu = select_lowest_power_cpu(&cpus_to_balance); + + cpumask_clear_cpu(balance_cpu, &cpus_to_balance); if (balance_cpu == this_cpu || !idle_cpu(balance_cpu)) continue; |
