summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorJoonwoo Park <joonwoop@codeaurora.org>2015-02-11 16:58:18 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:01:45 -0700
commitce35afd096b49eb58faa01d7a9e70deb4f7c6251 (patch)
tree397847ff14ace4d4d694fb234753d243ab8e1893 /kernel
parent73b7708de7deb4e45af2063944f52241083c81d7 (diff)
sched: actively migrate big tasks on power CPU to idle performance CPU
When performance CPU runs idle or newly idle load balancer to pull a task on power efficient CPU, the load balancer always fails and enters idle mode if the big task on the power efficient CPU is running. This is suboptimal when the running task on the power efficient CPU doesn't fit on the power efficient CPU as it's quite possible that the big task will sustain on the power efficient CPU until it's preempted while there is a performance CPU sitting idle. Revise load balancer algorithm to actively migrate big tasks on power efficient CPU to performance CPU when performance CPU runs idle or newly idle load balancer. Change-Id: Iaf05e0236955fdcc7ded0ff09af0880050a2be32 Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org> [rameezmustafa@codeaurora.org: Port to msm-3.18] Signed-off-by: Syed Rameez Mustafa <rameezmustafa@codeaurora.org> [joonwoop@codeaurora.org: fixed minor conflict in group_classify().] Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/fair.c87
1 files changed, 69 insertions, 18 deletions
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index da18be6d7bbe..6ef06d51c088 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7431,9 +7431,13 @@ enum fbq_type { regular, remote, all };
#define LBF_DST_PINNED 0x04
#define LBF_SOME_PINNED 0x08
#define LBF_IGNORE_SMALL_TASKS 0x10
-#define LBF_PWR_ACTIVE_BALANCE 0x20
-#define LBF_SCHED_BOOST 0x40
-#define LBF_IGNORE_BIG_TASKS 0x80
+#define LBF_EA_ACTIVE_BALANCE 0x20
+#define LBF_SCHED_BOOST_ACTIVE_BALANCE 0x40
+#define LBF_BIG_TASK_ACTIVE_BALANCE 0x80
+#define LBF_HMP_ACTIVE_BALANCE (LBF_EA_ACTIVE_BALANCE | \
+ LBF_SCHED_BOOST_ACTIVE_BALANCE | \
+ LBF_BIG_TASK_ACTIVE_BALANCE)
+#define LBF_IGNORE_BIG_TASKS 0x100
struct lb_env {
struct sched_domain *sd;
@@ -8289,12 +8293,12 @@ group_type group_classify(struct sched_group *group,
int cpu;
if (sgs->group_no_capacity) {
- env->flags &= ~LBF_PWR_ACTIVE_BALANCE;
+ env->flags &= ~LBF_EA_ACTIVE_BALANCE;
return group_overloaded;
}
if (sg_imbalanced(group)) {
- env->flags &= ~LBF_PWR_ACTIVE_BALANCE;
+ env->flags &= ~LBF_EA_ACTIVE_BALANCE;
return group_imbalanced;
}
@@ -8311,7 +8315,7 @@ group_type group_classify(struct sched_group *group,
power_cost_at_freq(cpu, 0) &&
!is_task_migration_throttled(cpu_rq(cpu)->curr) &&
is_cpu_throttling_imminent(cpu)) {
- env->flags |= LBF_PWR_ACTIVE_BALANCE;
+ env->flags |= LBF_EA_ACTIVE_BALANCE;
return group_ea;
}
@@ -8387,6 +8391,38 @@ static inline void update_sg_lb_stats(struct lb_env *env,
sgs->group_type = group_classify(group, sgs, env);
}
+#ifdef CONFIG_SCHED_HMP
+static bool update_sd_pick_busiest_active_balance(struct lb_env *env,
+ struct sd_lb_stats *sds,
+ struct sched_group *sg,
+ struct sg_lb_stats *sgs)
+{
+ if (env->idle != CPU_NOT_IDLE &&
+ capacity(env->dst_rq) > group_rq_capacity(sg)) {
+ if (sched_boost() && !sds->busiest && sgs->sum_nr_running) {
+ env->flags |= LBF_SCHED_BOOST_ACTIVE_BALANCE;
+ return true;
+ }
+
+ if (sgs->sum_nr_big_tasks >
+ sds->busiest_stat.sum_nr_big_tasks) {
+ env->flags |= LBF_BIG_TASK_ACTIVE_BALANCE;
+ return true;
+ }
+ }
+
+ return false;
+}
+#else
+static bool update_sd_pick_busiest_active_balance(struct lb_env *env,
+ struct sd_lb_stats *sds,
+ struct sched_group *sg,
+ struct sg_lb_stats *sgs)
+{
+ return false;
+}
+#endif
+
/**
* update_sd_pick_busiest - return 1 on busiest group
* @env: The load balancing environment.
@@ -8407,23 +8443,19 @@ static bool update_sd_pick_busiest(struct lb_env *env,
{
struct sg_lb_stats *busiest = &sds->busiest_stat;
- if (sched_boost() && !sds->busiest && sgs->sum_nr_running &&
- (env->idle != CPU_NOT_IDLE) && (capacity(env->dst_rq) >
- group_rq_capacity(sg))) {
- env->flags |= LBF_SCHED_BOOST;
+ if (update_sd_pick_busiest_active_balance(env, sds, sg, sgs))
return true;
- }
if (sgs->group_type > busiest->group_type)
return true;
if (sgs->group_type < busiest->group_type) {
if (sgs->group_type == group_ea)
- env->flags &= ~LBF_PWR_ACTIVE_BALANCE;
+ env->flags &= ~LBF_EA_ACTIVE_BALANCE;
return false;
}
- if (env->flags & LBF_PWR_ACTIVE_BALANCE) {
+ if (env->flags & LBF_EA_ACTIVE_BALANCE) {
if (power_cost_at_freq(group_first_cpu(sg), 0) <=
power_cost_at_freq(group_first_cpu(sds->busiest), 0))
return false;
@@ -8867,8 +8899,10 @@ out_balanced:
static struct rq *find_busiest_queue_hmp(struct lb_env *env,
struct sched_group *group)
{
- struct rq *busiest = NULL;
- u64 max_runnable_avg = 0;
+ struct rq *busiest = NULL, *busiest_big = NULL;
+ u64 max_runnable_avg = 0, max_runnable_avg_big = 0;
+ int max_nr_big = 0, nr_big;
+ bool find_big = !!(env->flags & LBF_BIG_TASK_ACTIVE_BALANCE);
int i;
for_each_cpu(i, sched_group_cpus(group)) {
@@ -8879,12 +8913,29 @@ static struct rq *find_busiest_queue_hmp(struct lb_env *env,
if (!cpumask_test_cpu(i, env->cpus))
continue;
+
+ if (find_big) {
+ nr_big = nr_big_tasks(rq);
+ if (nr_big > max_nr_big ||
+ (nr_big > 0 && nr_big == max_nr_big &&
+ cumulative_runnable_avg > max_runnable_avg_big)) {
+ max_runnable_avg_big = cumulative_runnable_avg;
+ busiest_big = rq;
+ max_nr_big = nr_big;
+ continue;
+ }
+ }
+
if (cumulative_runnable_avg > max_runnable_avg) {
max_runnable_avg = cumulative_runnable_avg;
busiest = rq;
}
}
+ if (busiest_big)
+ return busiest_big;
+
+ env->flags &= ~LBF_BIG_TASK_ACTIVE_BALANCE;
return busiest;
}
#else
@@ -8984,7 +9035,7 @@ static int need_active_balance(struct lb_env *env)
{
struct sched_domain *sd = env->sd;
- if (env->flags & (LBF_PWR_ACTIVE_BALANCE | LBF_SCHED_BOOST))
+ if (env->flags & LBF_HMP_ACTIVE_BALANCE)
return 1;
if (env->idle == CPU_NEWLY_IDLE) {
@@ -9227,7 +9278,7 @@ more_balance:
no_move:
if (!ld_moved) {
- if (!(env.flags & (LBF_PWR_ACTIVE_BALANCE | LBF_SCHED_BOOST)))
+ if (!(env.flags & LBF_HMP_ACTIVE_BALANCE))
schedstat_inc(sd, lb_failed[idle]);
/*
@@ -9237,7 +9288,7 @@ no_move:
* excessive cache_hot migrations and active balances.
*/
if (idle != CPU_NEWLY_IDLE &&
- !(env.flags & (LBF_PWR_ACTIVE_BALANCE | LBF_SCHED_BOOST)))
+ !(env.flags & LBF_HMP_ACTIVE_BALANCE))
sd->nr_balance_failed++;
if (need_active_balance(&env)) {