summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPavankumar Kondeti <pkondeti@codeaurora.org>2015-12-14 14:23:24 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 21:25:14 -0700
commit8cd1d7ef162d0911d18cf971c4a34c07bb994a80 (patch)
tree5919831710828c727fe46a0177f0a93ed5d38091 /kernel
parent6418f213abdc8823a7aa75fa4e504d3d83effa57 (diff)
sched: Take cluster's minimum power into account for optimizing sbc()
The select_best_cpu() algorithm iterates over all the clusters and selects the most power efficient CPU that satisfies the task needs. During the search, skip the next cluster if its minimum power cost is higher than the power cost of an eligible CPU found in the previous cluster. In a b.L system, if the BIG cluster minimum power cost is higher than the maximum power cost of the little cluster, this optimization avoids searching the BIG cluster if an eligible CPU is found in the little cluster. Change-Id: I5e3755f107edb6c72180edbec2a658be931c276d Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/core.c7
-rw-r--r--kernel/sched/fair.c14
-rw-r--r--kernel/sched/sched.h1
3 files changed, 18 insertions, 4 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 3eb27a016003..76e265ad1abf 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1298,6 +1298,7 @@ static struct sched_cluster init_cluster = {
.list = LIST_HEAD_INIT(init_cluster.list),
.id = 0,
.max_power_cost = 1,
+ .min_power_cost = 1,
.capacity = 1024,
.max_possible_capacity = 1024,
.efficiency = 1,
@@ -1398,9 +1399,12 @@ static void sort_clusters(void)
INIT_LIST_HEAD(&new_head);
- for_each_sched_cluster(cluster)
+ for_each_sched_cluster(cluster) {
cluster->max_power_cost = power_cost(cluster_first_cpu(cluster),
max_task_load());
+ cluster->min_power_cost = power_cost(cluster_first_cpu(cluster),
+ 0);
+ }
move_list(&new_head, &cluster_head, true);
@@ -1442,6 +1446,7 @@ static struct sched_cluster *alloc_new_cluster(const struct cpumask *cpus)
INIT_LIST_HEAD(&cluster->list);
cluster->max_power_cost = 1;
+ cluster->min_power_cost = 1;
cluster->capacity = 1024;
cluster->max_possible_capacity = 1024;
cluster->efficiency = 1;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 1cb4d18b1039..fc31d1b48a2d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3296,7 +3296,8 @@ struct cpu_select_env *env, struct cluster_cpu_stats *stats)
}
struct sched_cluster *
-next_best_cluster(struct sched_cluster *cluster, struct cpu_select_env *env)
+next_best_cluster(struct sched_cluster *cluster, struct cpu_select_env *env,
+ struct cluster_cpu_stats *stats)
{
struct sched_cluster *next = NULL;
@@ -3310,9 +3311,16 @@ next_best_cluster(struct sched_cluster *cluster, struct cpu_select_env *env)
return NULL;
next = next_candidate(env->candidate_list, 0, num_clusters);
- if (next)
+ if (next) {
+ if (next->min_power_cost > stats->min_cost) {
+ clear_bit(next->id, env->candidate_list);
+ next = NULL;
+ continue;
+ }
+
if (skip_cluster(next, env))
next = NULL;
+ }
} while (!next);
env->task_load = scale_load_to_cpu(task_load(env->p),
@@ -3529,7 +3537,7 @@ retry:
do {
find_best_cpu_in_cluster(cluster, &env, &stats);
- } while ((cluster = next_best_cluster(cluster, &env)));
+ } while ((cluster = next_best_cluster(cluster, &env, &stats)));
if (stats.best_idle_cpu >= 0) {
target = stats.best_idle_cpu;
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 2390f927f8c2..0185f664191b 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -374,6 +374,7 @@ struct sched_cluster {
struct cpumask cpus;
int id;
int max_power_cost;
+ int min_power_cost;
int max_possible_capacity;
int capacity;
int efficiency; /* Differentiate cpus with different IPC capability */