mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
soc: rockchip: rockchip_performance: optimize tasks schedule policy
When level==0(low-performance mode): 1. prefer prev_cpu for rt tasks if prev cpu is fit. 2. make sure that it saves at least 6% of the energy when migrate tasks from little cpu to big cpu. When level==2(high-performance mode): 1. do not use EAS path. 2. select big cpu first when system is not overutilized. 3. do not trigger load_balance() when system is not overutilized. 4. prefer prev_cpu for rt tasks if prev cpu is fit. Test performance improvement for level==2: 1. CONFIG_ROCKCHIP_PERFORMANCE=n EMMC Random Write(4KB) 25.44MB/s Antutu: Total 581266 CPU 133023 GPU 234106 MEM 103602 UX 110535 2. CONFIG_ROCKCHIP_PERFORMANCE=y and level==2 EMMC Random Write(4KB) 44.19MB/s (73.7% improvement) Antutu: Total 600483 (3.3% improvement) CPU 134481 (1.1% improvement) GPU 234678 MEM 116551 (12.5% improvement) UX 114773 (3.8% improvement) Change-Id: I949ac229864eb12159b886b7769e0b489345bef4 Signed-off-by: Liang Chen <cl@rock-chips.com>
This commit is contained in:
@@ -124,9 +124,26 @@ int rockchip_perf_get_level(void)
|
||||
return perf_level;
|
||||
}
|
||||
|
||||
struct cpumask *rockchip_perf_get_cpul_mask(void)
|
||||
{
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity))
|
||||
return cpul_mask;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cpumask *rockchip_perf_get_cpub_mask(void)
|
||||
{
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity))
|
||||
return cpub_mask;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
int rockchip_perf_select_rt_cpu(int prev_cpu, struct cpumask *lowest_mask)
|
||||
{
|
||||
struct cpumask target_mask;
|
||||
int cpu = nr_cpu_ids;
|
||||
|
||||
if (!perf_init_done)
|
||||
@@ -134,9 +151,14 @@ int rockchip_perf_select_rt_cpu(int prev_cpu, struct cpumask *lowest_mask)
|
||||
|
||||
if (static_branch_unlikely(&sched_asym_cpucapacity)) {
|
||||
if (perf_level == 0)
|
||||
cpu = cpumask_first_and(lowest_mask, cpul_mask);
|
||||
cpumask_and(&target_mask, lowest_mask, cpul_mask);
|
||||
if (perf_level == 2)
|
||||
cpu = cpumask_first_and(lowest_mask, cpub_mask);
|
||||
cpumask_and(&target_mask, lowest_mask, cpub_mask);
|
||||
|
||||
if (cpumask_test_cpu(prev_cpu, &target_mask))
|
||||
return prev_cpu;
|
||||
|
||||
cpu = cpumask_first(&target_mask);
|
||||
|
||||
if (cpu < nr_cpu_ids)
|
||||
return cpu;
|
||||
|
||||
@@ -5,13 +5,23 @@
|
||||
#ifndef __SOC_ROCKCHIP_PERFORMANCE_H
|
||||
#define __SOC_ROCKCHIP_PERFORMANCE_H
|
||||
|
||||
enum {
|
||||
ROCKCHIP_PERFORMANCE_LOW = 0,
|
||||
ROCKCHIP_PERFORMANCE_NORMAL,
|
||||
ROCKCHIP_PERFORMANCE_HIGH
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ROCKCHIP_PERFORMANCE
|
||||
extern int rockchip_perf_get_level(void);
|
||||
extern struct cpumask *rockchip_perf_get_cpul_mask(void);
|
||||
extern struct cpumask *rockchip_perf_get_cpub_mask(void);
|
||||
extern int rockchip_perf_select_rt_cpu(int prev_cpu, struct cpumask *lowest_mask);
|
||||
extern bool rockchip_perf_misfit_rt(int cpu);
|
||||
extern void rockchip_perf_uclamp_sync_util_min_rt_default(void);
|
||||
#else
|
||||
static inline int rockchip_perf_get_level(void) { return 1; }
|
||||
static inline int rockchip_perf_get_level(void) { return ROCKCHIP_PERFORMANCE_NORMAL; }
|
||||
static inline struct cpumask *rockchip_perf_get_cpul_mask(void) { return NULL; };
|
||||
static inline struct cpumask *rockchip_perf_get_cpub_mask(void) { return NULL; };
|
||||
static inline int rockchip_perf_select_rt_cpu(int prev_cpu, struct cpumask *lowest_mask)
|
||||
{
|
||||
return prev_cpu;
|
||||
|
||||
@@ -6347,6 +6347,11 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
||||
return recent_used_cpu;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
if (rockchip_perf_get_level() == ROCKCHIP_PERFORMANCE_HIGH)
|
||||
goto sd_llc;
|
||||
}
|
||||
|
||||
/*
|
||||
* For asymmetric CPU capacity systems, our domain of interest is
|
||||
* sd_asym_cpucapacity rather than sd_llc.
|
||||
@@ -6367,6 +6372,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
|
||||
}
|
||||
}
|
||||
|
||||
sd_llc:
|
||||
sd = rcu_dereference(per_cpu(sd_llc, target));
|
||||
if (!sd)
|
||||
return target;
|
||||
@@ -6808,9 +6814,22 @@ unlock:
|
||||
if (prev_delta == ULONG_MAX)
|
||||
return best_energy_cpu;
|
||||
|
||||
/*
|
||||
* when select ROCKCHIP_PERFORMANCE_LOW:
|
||||
* Pick best_energy_cpu immediately if prev_cpu is big cpu and
|
||||
* best_energy_cpu is little cpu, so that tasks can migrate from
|
||||
* big cpu to little cpu easier to save power.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
if (rockchip_perf_get_level() == 0)
|
||||
struct cpumask *cpul_mask = rockchip_perf_get_cpul_mask();
|
||||
struct cpumask *cpub_mask = rockchip_perf_get_cpub_mask();
|
||||
int level = rockchip_perf_get_level();
|
||||
|
||||
if ((level == ROCKCHIP_PERFORMANCE_LOW) && cpul_mask &&
|
||||
cpub_mask && cpumask_test_cpu(prev_cpu, cpub_mask) &&
|
||||
cpumask_test_cpu(best_energy_cpu, cpul_mask)) {
|
||||
return best_energy_cpu;
|
||||
}
|
||||
}
|
||||
|
||||
if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4))
|
||||
@@ -6857,6 +6876,11 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
|
||||
if (sd_flag & SD_BALANCE_WAKE) {
|
||||
record_wakee(p);
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
if (rockchip_perf_get_level() == ROCKCHIP_PERFORMANCE_HIGH)
|
||||
goto no_eas;
|
||||
}
|
||||
|
||||
if (sched_energy_enabled()) {
|
||||
new_cpu = find_energy_efficient_cpu(p, prev_cpu, sync);
|
||||
if (new_cpu >= 0)
|
||||
@@ -6864,6 +6888,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
|
||||
new_cpu = prev_cpu;
|
||||
}
|
||||
|
||||
no_eas:
|
||||
want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);
|
||||
}
|
||||
|
||||
@@ -6896,6 +6921,23 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
|
||||
|
||||
new_cpu = select_idle_sibling(p, prev_cpu, new_cpu);
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
struct root_domain *rd = cpu_rq(cpu)->rd;
|
||||
struct cpumask *cpul_mask = rockchip_perf_get_cpul_mask();
|
||||
struct cpumask *cpub_mask = rockchip_perf_get_cpub_mask();
|
||||
int level = rockchip_perf_get_level();
|
||||
|
||||
if ((level == ROCKCHIP_PERFORMANCE_HIGH) && !READ_ONCE(rd->overutilized) &&
|
||||
cpul_mask && cpub_mask && cpumask_intersects(p->cpus_ptr, cpub_mask) &&
|
||||
cpumask_test_cpu(new_cpu, cpul_mask)) {
|
||||
for_each_domain(cpu, tmp) {
|
||||
sd = tmp;
|
||||
}
|
||||
if (sd)
|
||||
new_cpu = find_idlest_cpu(sd, p, cpu, prev_cpu, sd_flag);
|
||||
}
|
||||
}
|
||||
|
||||
if (want_affine)
|
||||
current->recent_used_cpu = cpu;
|
||||
}
|
||||
@@ -8975,6 +9017,17 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
|
||||
do {
|
||||
int local_group;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
struct root_domain *rd = cpu_rq(this_cpu)->rd;
|
||||
struct cpumask *cpub_mask = rockchip_perf_get_cpub_mask();
|
||||
int level = rockchip_perf_get_level();
|
||||
|
||||
if ((level == ROCKCHIP_PERFORMANCE_HIGH) && !READ_ONCE(rd->overutilized) &&
|
||||
cpub_mask && cpumask_intersects(p->cpus_ptr, cpub_mask) &&
|
||||
!cpumask_intersects(sched_group_span(group), cpub_mask))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Skip over this group if it has no CPUs allowed */
|
||||
if (!cpumask_intersects(sched_group_span(group),
|
||||
p->cpus_ptr))
|
||||
@@ -9701,6 +9754,16 @@ static int should_we_balance(struct lb_env *env)
|
||||
struct sched_group *sg = env->sd->groups;
|
||||
int cpu;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_PERFORMANCE)) {
|
||||
struct root_domain *rd = env->dst_rq->rd;
|
||||
struct cpumask *cpul_mask = rockchip_perf_get_cpul_mask();
|
||||
int level = rockchip_perf_get_level();
|
||||
|
||||
if ((level == ROCKCHIP_PERFORMANCE_HIGH) && !READ_ONCE(rd->overutilized) &&
|
||||
cpul_mask && cpumask_test_cpu(env->dst_cpu, cpul_mask))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the balancing environment is consistent; can happen
|
||||
* when the softirq triggers 'during' hotplug.
|
||||
|
||||
Reference in New Issue
Block a user