sched: fine tune task placement for prioritized tasks
The prioritized task is defined as prefer high capacity with prio <= 120. We found on the chipset with 2 big cores only, when one big core is occupied by busy non-prioritized tasks, prioritized tasks could be scheduled to the other big core. This may affect UX because the prioritized tasks are mostly UI related. Address this problem by put at least one prioritized task to the cpu which has no prioritized task running on it. Besides, if both big cores have prioritized tasks on them already, then schedule arriving prioritized tasks to idle little core if there is in the hope of not being blocked by existing prioritized tasks. Bug: 161190988 Bug: 160663228 Test: tasks scheduled as expected Signed-off-by: Rick Yiu <rickyiu@google.com> Change-Id: I880e3a68a5c8fbfd0902e1b571a83bfd88ce1b96
This commit is contained in:
parent
dcbacf46fa
commit
aa57fb3819
@ -7207,6 +7207,8 @@ static struct kmem_cache *task_group_cache __read_mostly;
|
||||
|
||||
DECLARE_PER_CPU(cpumask_var_t, load_balance_mask);
|
||||
DECLARE_PER_CPU(cpumask_var_t, select_idle_mask);
|
||||
DECLARE_PER_CPU(unsigned long *, prioritized_task_mask);
|
||||
DECLARE_PER_CPU(int, prioritized_task_nr);
|
||||
|
||||
void __init sched_init(void)
|
||||
{
|
||||
@ -7279,6 +7281,9 @@ void __init sched_init(void)
|
||||
rq = cpu_rq(i);
|
||||
raw_spin_lock_init(&rq->lock);
|
||||
rq->nr_running = 0;
|
||||
per_cpu(prioritized_task_mask, i) =
|
||||
bitmap_zalloc(TASK_BITS, GFP_KERNEL);
|
||||
per_cpu(prioritized_task_nr, i) = 0;
|
||||
rq->calc_load_active = 0;
|
||||
rq->calc_load_update = jiffies + LOAD_FREQ;
|
||||
init_cfs_rq(&rq->cfs);
|
||||
|
@ -167,9 +167,11 @@ unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL;
|
||||
*/
|
||||
unsigned int capacity_margin = 1280;
|
||||
unsigned int sched_capacity_margin_up[CPU_NR] = {
|
||||
[0 ... CPU_NR-1] = 1078}; /* ~5% margin */
|
||||
[0 ... CPU_NR - 1] = 1078
|
||||
}; /* ~5% margin */
|
||||
unsigned int sched_capacity_margin_down[CPU_NR] = {
|
||||
[0 ... CPU_NR-1] = 1205}; /* ~15% margin */
|
||||
[0 ... CPU_NR - 1] = 1078
|
||||
}; /* ~5% margin */
|
||||
unsigned int sched_capacity_margin_up_boosted[CPU_NR] = {
|
||||
3658, 3658, 3658, 3658, 3658, 3658, 1078, 1024
|
||||
}; /* 72% margin for small, 5% for big, 0% for big+ */
|
||||
@ -2830,6 +2832,47 @@ static inline void update_scan_period(struct task_struct *p, int new_cpu)
|
||||
|
||||
#endif /* CONFIG_NUMA_BALANCING */
|
||||
|
||||
DEFINE_PER_CPU(unsigned long *, prioritized_task_mask);
|
||||
DEFINE_PER_CPU(int, prioritized_task_nr);
|
||||
|
||||
static bool bitmap_testbit(unsigned long *map, unsigned long bit)
|
||||
{
|
||||
if (*(map + BIT_WORD(bit)) & BIT_MASK(bit))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void inc_prioritized_task_count(struct rq *rq, struct task_struct *p)
|
||||
{
|
||||
bool bitset = bitmap_testbit(per_cpu(prioritized_task_mask, cpu_of(rq)),
|
||||
p->pid);
|
||||
|
||||
if (schedtune_prefer_high_cap(p) && p->prio <= DEFAULT_PRIO) {
|
||||
if (likely(!bitset)) {
|
||||
__bitmap_set(per_cpu(prioritized_task_mask, cpu_of(rq)),
|
||||
p->pid, 1);
|
||||
per_cpu(prioritized_task_nr, cpu_of(rq))++;
|
||||
}
|
||||
} else if (unlikely(bitset)) {
|
||||
__bitmap_clear(per_cpu(prioritized_task_mask, cpu_of(rq)),
|
||||
p->pid, 1);
|
||||
if (per_cpu(prioritized_task_nr, cpu_of(rq)) > 0)
|
||||
per_cpu(prioritized_task_nr, cpu_of(rq))--;
|
||||
}
|
||||
}
|
||||
|
||||
static void dec_prioritized_task_count(struct rq *rq, struct task_struct *p)
|
||||
{
|
||||
if (bitmap_testbit(per_cpu(prioritized_task_mask, cpu_of(rq)),
|
||||
p->pid)) {
|
||||
__bitmap_clear(per_cpu(prioritized_task_mask, cpu_of(rq)),
|
||||
p->pid, 1);
|
||||
if (per_cpu(prioritized_task_nr, cpu_of(rq)) > 0)
|
||||
per_cpu(prioritized_task_nr, cpu_of(rq))--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
|
||||
{
|
||||
@ -2845,6 +2888,9 @@ account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se)
|
||||
}
|
||||
#endif
|
||||
cfs_rq->nr_running++;
|
||||
if (likely(entity_is_task(se))) {
|
||||
inc_prioritized_task_count(rq_of(cfs_rq), task_of(se));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2860,6 +2906,9 @@ account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se)
|
||||
}
|
||||
#endif
|
||||
cfs_rq->nr_running--;
|
||||
if (likely(entity_is_task(se))) {
|
||||
dec_prioritized_task_count(rq_of(cfs_rq), task_of(se));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3936,7 +3985,7 @@ static inline bool cpu_is_in_target_set(struct task_struct *p, int cpu)
|
||||
struct root_domain *rd = cpu_rq(cpu)->rd;
|
||||
int first_cpu, next_usable_cpu;
|
||||
#ifdef CONFIG_SCHED_TUNE
|
||||
if (schedtune_prefer_high_cap(p)) {
|
||||
if (schedtune_prefer_high_cap(p) && p->prio <= DEFAULT_PRIO) {
|
||||
#else
|
||||
if (uclamp_boosted(p)) {
|
||||
#endif
|
||||
@ -7068,6 +7117,7 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
struct sched_group *sg;
|
||||
int best_active_cpu = -1;
|
||||
int best_idle_cpu = -1;
|
||||
int best_prioritized_cpu = -1;
|
||||
int target_cpu = -1;
|
||||
int backup_cpu = -1;
|
||||
int i, start_cpu;
|
||||
@ -7080,6 +7130,7 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
bool rtg_high_prio_task = task_rtg_high_prio(p);
|
||||
int mid_cap_orig_cpu = cpu_rq(smp_processor_id())->rd->mid_cap_orig_cpu;
|
||||
struct task_struct *curr_tsk;
|
||||
bool prioritized_task = prefer_high_cap && p->prio <= DEFAULT_PRIO;
|
||||
|
||||
/*
|
||||
* In most cases, target_capacity tracks capacity_orig of the most
|
||||
@ -7126,6 +7177,7 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
unsigned long wake_util, new_util, new_util_cuml;
|
||||
long spare_cap;
|
||||
int idle_idx = INT_MAX;
|
||||
bool best_prioritized_candidate;
|
||||
|
||||
trace_sched_cpu_util(i);
|
||||
|
||||
@ -7187,7 +7239,12 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
* capacity margin.
|
||||
*/
|
||||
new_util = max(min_util, new_util);
|
||||
best_prioritized_candidate =
|
||||
prioritized_task && !is_min_capacity_cpu(i) &&
|
||||
per_cpu(prioritized_task_nr, i) == 0;
|
||||
|
||||
if ((!(prefer_idle && idle_cpu(i)) &&
|
||||
!best_prioritized_candidate &&
|
||||
new_util > capacity_orig) ||
|
||||
(is_min_capacity_cpu(i) &&
|
||||
!task_fits_capacity(p, capacity_orig, i)))
|
||||
@ -7284,6 +7341,11 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
if (best_idle_cpu != -1)
|
||||
continue;
|
||||
|
||||
if (best_prioritized_candidate) {
|
||||
best_prioritized_cpu = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Case A.2: Target ACTIVE CPU
|
||||
* Favor CPUs with max spare capacity.
|
||||
@ -7465,10 +7527,11 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
* accommodated in the higher capacity CPUs.
|
||||
*/
|
||||
if ((prefer_idle && best_idle_cpu != -1) ||
|
||||
(prefer_high_cap &&
|
||||
(best_idle_cpu != -1 || target_cpu != -1 ||
|
||||
(prioritized_task && best_prioritized_cpu != -1) ||
|
||||
(prefer_high_cap && p->prio > DEFAULT_PRIO &&
|
||||
(target_cpu != -1 ||
|
||||
(fbt_env->strict_max && most_spare_cap_cpu != -1)))) {
|
||||
if (prefer_high_cap && p->prio <= DEFAULT_PRIO) {
|
||||
if (prioritized_task) {
|
||||
/*
|
||||
* For prefer_high_cap task, stop searching when
|
||||
* an idle cpu is found in mid cluster.
|
||||
@ -7490,6 +7553,11 @@ static void find_best_target(struct sched_domain *sd, cpumask_t *cpus,
|
||||
goto target;
|
||||
}
|
||||
|
||||
if (prioritized_task && (best_prioritized_cpu != -1)) {
|
||||
target_cpu = best_prioritized_cpu;
|
||||
goto target;
|
||||
}
|
||||
|
||||
adjust_cpus_for_packing(p, &target_cpu, &best_idle_cpu,
|
||||
shallowest_idle_cstate,
|
||||
fbt_env, prefer_high_cap);
|
||||
@ -8894,9 +8962,11 @@ static inline int migrate_degrades_locality(struct task_struct *p,
|
||||
static inline bool can_migrate_boosted_task(struct task_struct *p,
|
||||
int src_cpu, int dst_cpu)
|
||||
{
|
||||
if (per_task_boost(p) == TASK_BOOST_STRICT_MAX &&
|
||||
if ((per_task_boost(p) == TASK_BOOST_STRICT_MAX &&
|
||||
task_in_related_thread_group(p) &&
|
||||
(capacity_orig_of(dst_cpu) < capacity_orig_of(src_cpu)))
|
||||
(capacity_orig_of(dst_cpu) < capacity_orig_of(src_cpu))) ||
|
||||
(schedtune_prefer_high_cap(p) && p->prio <= DEFAULT_PRIO &&
|
||||
is_min_capacity_cpu(dst_cpu)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -89,6 +89,8 @@ struct cpuidle_state;
|
||||
|
||||
#define CPU_NR 8
|
||||
|
||||
#define TASK_BITS (PID_MAX_DEFAULT + BITS_PER_LONG)
|
||||
|
||||
extern __read_mostly bool sched_predl;
|
||||
extern unsigned int sched_capacity_margin_up[CPU_NR];
|
||||
extern unsigned int sched_capacity_margin_down[CPU_NR];
|
||||
|
Loading…
Reference in New Issue
Block a user