Skip to content

Commit c82a696

Browse files
vingu-linaroPeter Zijlstra
authored andcommitted
sched/fair: fix case with reduced capacity CPU
The capacity of the CPU available for CFS tasks can be reduced because of other activities running on the latter. In such case, it's worth trying to move CFS tasks on a CPU with more available capacity. The rework of the load balance has filtered the case when the CPU is classified to be fully busy but its capacity is reduced. Check if CPU's capacity is reduced while gathering load balance statistic and classify it group_misfit_task instead of group_fully_busy so we can try to move the load on another CPU. Reported-by: David Chen <[email protected]> Reported-by: Zhang Qiao <[email protected]> Signed-off-by: Vincent Guittot <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: David Chen <[email protected]> Tested-by: Zhang Qiao <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent c02d554 commit c82a696

File tree

1 file changed

+42
-12
lines changed

1 file changed

+42
-12
lines changed

kernel/sched/fair.c

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7711,8 +7711,8 @@ enum group_type {
77117711
*/
77127712
group_fully_busy,
77137713
/*
7714-
* SD_ASYM_CPUCAPACITY only: One task doesn't fit with CPU's capacity
7715-
* and must be migrated to a more powerful CPU.
7714+
* One task doesn't fit with CPU's capacity and must be migrated to a
7715+
* more powerful CPU.
77167716
*/
77177717
group_misfit_task,
77187718
/*
@@ -8798,6 +8798,19 @@ sched_asym(struct lb_env *env, struct sd_lb_stats *sds, struct sg_lb_stats *sgs
87988798
return sched_asym_prefer(env->dst_cpu, group->asym_prefer_cpu);
87998799
}
88008800

8801+
static inline bool
8802+
sched_reduced_capacity(struct rq *rq, struct sched_domain *sd)
8803+
{
8804+
/*
8805+
* When there is more than 1 task, the group_overloaded case already
8806+
* takes care of cpu with reduced capacity
8807+
*/
8808+
if (rq->cfs.h_nr_running != 1)
8809+
return false;
8810+
8811+
return check_cpu_capacity(rq, sd);
8812+
}
8813+
88018814
/**
88028815
* update_sg_lb_stats - Update sched_group's statistics for load balancing.
88038816
* @env: The load balancing environment.
@@ -8820,8 +8833,9 @@ static inline void update_sg_lb_stats(struct lb_env *env,
88208833

88218834
for_each_cpu_and(i, sched_group_span(group), env->cpus) {
88228835
struct rq *rq = cpu_rq(i);
8836+
unsigned long load = cpu_load(rq);
88238837

8824-
sgs->group_load += cpu_load(rq);
8838+
sgs->group_load += load;
88258839
sgs->group_util += cpu_util_cfs(i);
88268840
sgs->group_runnable += cpu_runnable(rq);
88278841
sgs->sum_h_nr_running += rq->cfs.h_nr_running;
@@ -8851,11 +8865,17 @@ static inline void update_sg_lb_stats(struct lb_env *env,
88518865
if (local_group)
88528866
continue;
88538867

8854-
/* Check for a misfit task on the cpu */
8855-
if (env->sd->flags & SD_ASYM_CPUCAPACITY &&
8856-
sgs->group_misfit_task_load < rq->misfit_task_load) {
8857-
sgs->group_misfit_task_load = rq->misfit_task_load;
8858-
*sg_status |= SG_OVERLOAD;
8868+
if (env->sd->flags & SD_ASYM_CPUCAPACITY) {
8869+
/* Check for a misfit task on the cpu */
8870+
if (sgs->group_misfit_task_load < rq->misfit_task_load) {
8871+
sgs->group_misfit_task_load = rq->misfit_task_load;
8872+
*sg_status |= SG_OVERLOAD;
8873+
}
8874+
} else if ((env->idle != CPU_NOT_IDLE) &&
8875+
sched_reduced_capacity(rq, env->sd)) {
8876+
/* Check for a task running on a CPU with reduced capacity */
8877+
if (sgs->group_misfit_task_load < load)
8878+
sgs->group_misfit_task_load = load;
88598879
}
88608880
}
88618881

@@ -8908,7 +8928,8 @@ static bool update_sd_pick_busiest(struct lb_env *env,
89088928
* CPUs in the group should either be possible to resolve
89098929
* internally or be covered by avg_load imbalance (eventually).
89108930
*/
8911-
if (sgs->group_type == group_misfit_task &&
8931+
if ((env->sd->flags & SD_ASYM_CPUCAPACITY) &&
8932+
(sgs->group_type == group_misfit_task) &&
89128933
(!capacity_greater(capacity_of(env->dst_cpu), sg->sgc->max_capacity) ||
89138934
sds->local_stat.group_type != group_has_spare))
89148935
return false;
@@ -9517,9 +9538,18 @@ static inline void calculate_imbalance(struct lb_env *env, struct sd_lb_stats *s
95179538
busiest = &sds->busiest_stat;
95189539

95199540
if (busiest->group_type == group_misfit_task) {
9520-
/* Set imbalance to allow misfit tasks to be balanced. */
9521-
env->migration_type = migrate_misfit;
9522-
env->imbalance = 1;
9541+
if (env->sd->flags & SD_ASYM_CPUCAPACITY) {
9542+
/* Set imbalance to allow misfit tasks to be balanced. */
9543+
env->migration_type = migrate_misfit;
9544+
env->imbalance = 1;
9545+
} else {
9546+
/*
9547+
* Set load imbalance to allow moving task from cpu
9548+
* with reduced capacity.
9549+
*/
9550+
env->migration_type = migrate_load;
9551+
env->imbalance = busiest->group_misfit_task_load;
9552+
}
95239553
return;
95249554
}
95259555

0 commit comments

Comments
 (0)