mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
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:
committed by
Mauro (mdrjr) Ribeiro
parent
77c044cf30
commit
a35492a605
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user