Current code if over tipping point, the all tasks will be spread out. So this will hurt power if there have only one big task with many other small tasks. So add criteria to filter out task to force energy aware path: the first one is the task has set boost margin, then means the task should be controlled well by PE filter rather than spread by SMP load balance. The second one is: if we can find more lower capacity CPU can meet the task computation requirement, then also consider to force to energy aware path.
Signed-off-by: Leo Yan leo.yan@linaro.org --- kernel/sched/fair.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 594d050..604793d 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5339,6 +5339,41 @@ static bool need_spread_task(int cpu) return spread; }
+static bool need_filter_task(struct task_struct *p) +{ + int cpu = task_cpu(p); + int origin_max_cap = capacity_orig_of(cpu); + int target_max_cap = cpu_rq(cpu)->rd->max_cpu_capacity.val; + unsigned long margin = schedtune_task_margin(p); + struct sched_domain *sd; + struct sched_group *sg; + + if (margin) + return 1; + + sd = rcu_dereference(per_cpu(sd_ea, cpu)); + if (!sd) + return 0; + + sg = sd->groups; + do { + int first_cpu = group_first_cpu(sg); + + if (capacity_orig_of(first_cpu) < target_max_cap && + task_util(p) * 4 < capacity_orig_of(first_cpu)) + target_max_cap = capacity_orig_of(first_cpu); + + } while (sg = sg->next, sg != sd->groups); + + if (capacity_orig_of(smp_processor_id()) > target_max_cap) + return 1; + + if (target_max_cap < origin_max_cap) + return 1; + + return 0; +} + #ifdef CONFIG_SCHED_TUNE
static long @@ -5964,7 +5999,8 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f }
if (!sd) { - if (energy_aware() && !need_spread_task(cpu)) + if (energy_aware() && + (!need_spread_task(cpu) || need_filter_task(p))) new_cpu = energy_aware_wake_cpu(p, prev_cpu, sync); else if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */ new_cpu = select_idle_sibling(p, new_cpu); -- 1.9.1