When CPUs have different capacity because of RT/DL tasks or
micro-architecture or max frequency differences, there are situation where
the imbalance is not correctly set to migrate waiting task on the idle CPU.

The UC uses the force_balance case :
        if (env->idle != CPU_NOT_IDLE && group_has_capacity(env, local) &&
            busiest->group_no_capacity)
                goto force_balance;

But calculate_imbalance fails to set the right amount of load to migrate
a task because of the special condition:
  busiest->avg_load <= sds->avg_load || local->avg_load >= sds->avg_load)

Add in fix_small_imbalance, this special case that triggered the force
balance in order to make sure that the amount of load to migrate will be
enough.

Signed-off-by: Vincent Guittot <vincent.guit...@linaro.org>
---
 kernel/sched/fair.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 309c93f..72bc5e8 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -8048,6 +8048,20 @@ void fix_small_imbalance(struct lb_env *env, struct 
sd_lb_stats *sds)
        local = &sds->local_stat;
        busiest = &sds->busiest_stat;
 
+       /*
+        * There is available capacity in local group and busiest group is
+        * overloaded but calculate_imbalance can't compute the amount of load
+        * to migrate because load_avg became meaningless due to asymetric
+        * capacity between groups. In such case, we only want to migrate at
+        * least one tasks of the busiest group and rely of the average load
+        * per task to ensure the migration.
+        */
+       if (env->idle != CPU_NOT_IDLE && group_has_capacity(env, local) &&
+           busiest->group_no_capacity) {
+               env->imbalance = busiest->load_per_task;
+               return;
+       }
+
        if (!local->sum_nr_running)
                local->load_per_task = cpu_avg_load_per_task(env->dst_cpu);
        else if (busiest->load_per_task > local->load_per_task)
-- 
2.7.4

Reply via email to