[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1536334803-21059-1-git-send-email-vincent.guittot@linaro.org>
Date: Fri, 7 Sep 2018 17:40:03 +0200
From: Vincent Guittot <vincent.guittot@...aro.org>
To: peterz@...radead.org, mingo@...nel.org,
linux-kernel@...r.kernel.org
Cc: dietmar.eggemann@....com, Morten.Rasmussen@....com,
valentin.schneider@....com,
Vincent Guittot <vincent.guittot@...aro.org>
Subject: [PATCH] sched/fair: fix 1 task per CPU
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.guittot@...aro.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..57b4d83 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 they became meaningless because asymetric
+ * capacity between group. 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
Powered by blists - more mailing lists