OSDN Git Service

sched/fair: discount task contribution to find CPU with lowest utilization
authorValentin Schneider <valentin.schneider@arm.com>
Fri, 3 Mar 2017 11:43:03 +0000 (11:43 +0000)
committerAndres Oportus <andresoportus@google.com>
Fri, 2 Jun 2017 15:01:54 +0000 (08:01 -0700)
In some cases, the new_util of a task can be the same on several
CPUs. This causes an issue because the target_util is only updated
if the current new_util is strictly smaller than target_util.

To fix that, the cpu_util_wake() return value is used alongside the
new_util value. If two CPUs compute the same new_util value,
we'll now also look at their cpu_util_wake() return value. In this
case, the CPU that last ran the task will be chosen in priority.

Change-Id: Ia1ea2c4b3ec39621372c2f748862317d5b497723
Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
kernel/sched/fair.c

index 23e2b5f..fc4e252 100644 (file)
@@ -6221,7 +6221,8 @@ static inline int find_best_target(struct task_struct *p, bool boosted, bool pre
                int i;
 
                for_each_cpu_and(i, tsk_cpus_allowed(p), sched_group_cpus(sg)) {
-                       unsigned long cur_capacity, new_util;
+                       unsigned long cur_capacity, new_util, wake_util;
+                       unsigned long min_wake_util = ULONG_MAX;
 
                        if (!cpu_online(i))
                                continue;
@@ -6231,7 +6232,8 @@ static inline int find_best_target(struct task_struct *p, bool boosted, bool pre
                         * so prev_cpu will receive a negative bias due to the double
                         * accounting. However, the blocked utilization may be zero.
                         */
-                       new_util = cpu_util_wake(i, p) + task_util(p);
+                       wake_util = cpu_util_wake(i, p);
+                       new_util = wake_util + task_util(p);
 
                        /*
                         * Ensure minimum capacity to grant the required boost.
@@ -6266,8 +6268,15 @@ static inline int find_best_target(struct task_struct *p, bool boosted, bool pre
                                         * Find a target cpu with the lowest/highest
                                         * utilization if prefer_idle/!prefer_idle.
                                         */
-                                       if ((prefer_idle && target_util > new_util) ||
-                                           (!prefer_idle && target_util < new_util)) {
+                                       if (prefer_idle) {
+                                               /* Favor the CPU that last ran the task */
+                                               if (new_util > target_util ||
+                                                   wake_util > min_wake_util)
+                                                       continue;
+                                               min_wake_util = wake_util;
+                                               target_util = new_util;
+                                               target_cpu = i;
+                                       } else if (target_util < new_util) {
                                                target_util = new_util;
                                                target_cpu = i;
                                        }