95 lines
2.5 KiB
C
Executable File
95 lines
2.5 KiB
C
Executable File
/*
|
|
* Performance CPU Finder
|
|
*
|
|
* Copyright (C) 2018 Samsung Electronics Co., Ltd
|
|
* Park Bumgyu <bumgyu.park@samsung.com>
|
|
*/
|
|
|
|
#include <trace/events/ems.h>
|
|
|
|
#include "ems.h"
|
|
#include "../sched.h"
|
|
|
|
/*
|
|
* Currently, PCF is composed of a selection algorithm based on distributed
|
|
* processing, for example, selecting idle cpu or cpu with biggest spare
|
|
* capacity. Although the current algorithm may suffice, it is necessary to
|
|
* examine a selection algorithm considering cache hot and migration cost.
|
|
*/
|
|
int select_perf_cpu(struct task_struct *p)
|
|
{
|
|
int cpu;
|
|
unsigned long best_perf_cap_orig = 0;
|
|
unsigned long max_spare_cap = 0;
|
|
int best_perf_cstate = INT_MAX;
|
|
int best_perf_cpu = -1;
|
|
int backup_cpu = -1;
|
|
|
|
rcu_read_lock();
|
|
|
|
for_each_cpu_and(cpu, &p->cpus_allowed, cpu_active_mask) {
|
|
unsigned long capacity_orig = capacity_orig_of(cpu);
|
|
unsigned long wake_util;
|
|
|
|
/*
|
|
* A) Find best performance cpu.
|
|
*
|
|
* If the impact of cache hot and migration cost are excluded,
|
|
* distributed processing is the best way to achieve performance.
|
|
* To maximize performance, the idle cpu with the highest
|
|
* performance is selected first. If there are more than two idle
|
|
* cpus with the highest performance, choose the cpu with the
|
|
* shallowest idle state for fast reactivity.
|
|
*/
|
|
if (idle_cpu(cpu)) {
|
|
int idle_idx = idle_get_state_idx(cpu_rq(cpu));
|
|
|
|
/* find biggest capacity cpu */
|
|
if (capacity_orig < best_perf_cap_orig)
|
|
continue;
|
|
|
|
/*
|
|
* if we find a better-performing cpu, re-initialize
|
|
* best_perf_cstate
|
|
*/
|
|
if (capacity_orig > best_perf_cap_orig) {
|
|
best_perf_cap_orig = capacity_orig;
|
|
best_perf_cstate = INT_MAX;
|
|
}
|
|
|
|
/* find shallowest idle state cpu */
|
|
if (idle_idx >= best_perf_cstate)
|
|
continue;
|
|
|
|
/* Keep track of best idle CPU */
|
|
best_perf_cstate = idle_idx;
|
|
best_perf_cpu = cpu;
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* B) Find backup performance cpu.
|
|
*
|
|
* Backup cpu also adopts distributed processing. In the absence
|
|
* of idle cpu, it is difficult to expect reactivity, so select
|
|
* the cpu with the biggest spare capacity to handle the most
|
|
* computations. Since a high performance cpu has a large capacity,
|
|
* cpu having a high performance is likely to be selected.
|
|
*/
|
|
wake_util = cpu_util_wake(cpu, p);
|
|
if ((capacity_orig - wake_util) < max_spare_cap)
|
|
continue;
|
|
|
|
max_spare_cap = capacity_orig - wake_util;
|
|
backup_cpu = cpu;
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
trace_ems_select_perf_cpu(p, best_perf_cpu, backup_cpu);
|
|
if (best_perf_cpu == -1)
|
|
return backup_cpu;
|
|
|
|
return best_perf_cpu;
|
|
}
|