hperf_hmp: task CPU selection logic.

or it is not WF_SYNC wakeup, idlest CPU from both clusters is selected. Else,
default wake up logic is used('want_affine'). If it fails, idlest CPU from both
clusters is selected.

Signed-off-by: Tarek Dakhran <t.dakhran <at> samsung.com>
Signed-off-by: Sergey Dyasly <s.dyasly <at> samsung.com>
Signed-off-by: Dmitriy Safonov <d.safonov <at> partner.samsung.com>
Signed-off-by: Arseniy Krasnov <a.krasnov <at> samsung.com>
Signed-off-by: Ilya Maximets <i.maximets <at> samsung.com>
Signed-off-by: memeka <mihailescu2m@gmail.com>
This commit is contained in:
Arseniy Krasnov
2015-11-06 12:02:45 +00:00
committed by Mauro (mdrjr) Ribeiro
parent 77c044cf30
commit a35492a605

View File

@@ -5331,6 +5331,62 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p,
return 1;
}
#ifdef CONFIG_HPERF_HMP
/**
* hmp_select_task_rq_fair(): selects cpu for task.
* @p: task which needs cpu
*
* Returns cpu for task.
*
* Selects idlest cpu for task @p.
*/
static int
hmp_select_task_rq_fair(struct task_struct *p)
{
int cpu;
int new_cpu;
unsigned long load;
unsigned long scaled_load;
new_cpu = task_cpu(p);
load = ULONG_MAX;
/* First check primary cpus */
for_each_cpu_and(cpu, cpu_online_mask, cpu_fastest_mask) {
if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) {
/* Select idle cpu if it exists */
if (idle_cpu(cpu))
return cpu;
/* Otherwise select the least loaded cpu */
scaled_load = (weighted_cpuload(cpu) *
SCHED_CAPACITY_SCALE) /
freq_scale_cpu_power[cpu];
if (scaled_load < load) {
new_cpu = cpu;
load = scaled_load;
}
}
}
/* Then check secondary cpus */
for_each_cpu_and(cpu, cpu_online_mask, cpu_slowest_mask) {
if (cpumask_test_cpu(cpu, tsk_cpus_allowed(p))) {
if (idle_cpu(cpu))
return cpu;
scaled_load = (weighted_cpuload(cpu) *
SCHED_CAPACITY_SCALE) /
freq_scale_cpu_power[cpu];
if (scaled_load < load) {
new_cpu = cpu;
load = scaled_load;
}
}
}
return new_cpu;
}
#else /* CONFIG_HPERF_HMP */
/*
* find_idlest_group finds and returns the least busy CPU group within the
* domain.
@@ -5442,6 +5498,7 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu)
return shallowest_idle_cpu != -1 ? shallowest_idle_cpu : least_loaded_cpu;
}
#endif /* CONFIG_HPERF_HMP */
/*
* Implement a for_each_cpu() variant that starts the scan at a given cpu
* (@start), and wraps around.
@@ -5763,6 +5820,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
int want_affine = 0;
int sync = wake_flags & WF_SYNC;
#ifdef CONFIG_HPERF_HMP
if (!(sd_flag & SD_BALANCE_WAKE) || !sync)
return hmp_select_task_rq_fair(p);
#endif
if (sd_flag & SD_BALANCE_WAKE) {
record_wakee(p);
want_affine = !wake_wide(p) && !wake_cap(p, cpu, prev_cpu)
@@ -5798,41 +5860,49 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
if (!sd) {
if (sd_flag & SD_BALANCE_WAKE) /* XXX always ? */
new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);
if (IS_ENABLED(CONFIG_HPERF_HMP) && sync)
new_cpu = prev_cpu;
else
new_cpu = select_idle_sibling(p, prev_cpu);
} else {
#ifdef CONFIG_HPERF_HMP
new_cpu = hmp_select_task_rq_fair(p);
#else
while (sd) {
struct sched_group *group;
int weight;
} else while (sd) {
struct sched_group *group;
int weight;
if (!(sd->flags & sd_flag)) {
sd = sd->child;
continue;
}
if (!(sd->flags & sd_flag)) {
sd = sd->child;
continue;
}
group = find_idlest_group(sd, p, cpu, sd_flag);
if (!group) {
sd = sd->child;
continue;
}
group = find_idlest_group(sd, p, cpu, sd_flag);
if (!group) {
sd = sd->child;
continue;
}
new_cpu = find_idlest_cpu(group, p, cpu);
if (new_cpu == -1 || new_cpu == cpu) {
/* Now try balancing at a lower domain level of cpu */
sd = sd->child;
continue;
}
new_cpu = find_idlest_cpu(group, p, cpu);
if (new_cpu == -1 || new_cpu == cpu) {
/* Now try balancing at a lower domain level of cpu */
sd = sd->child;
continue;
}
/* Now try balancing at a lower domain level of new_cpu */
cpu = new_cpu;
weight = sd->span_weight;
sd = NULL;
for_each_domain(cpu, tmp) {
if (weight <= tmp->span_weight)
break;
if (tmp->flags & sd_flag)
sd = tmp;
}
/* while loop will break here if sd == NULL */
/* Now try balancing at a lower domain level of new_cpu */
cpu = new_cpu;
weight = sd->span_weight;
sd = NULL;
for_each_domain(cpu, tmp) {
if (weight <= tmp->span_weight)
break;
if (tmp->flags & sd_flag)
sd = tmp;
}
/* while loop will break here if sd == NULL */
}
#endif
}
rcu_read_unlock();