hmp: dont attempt to pull tasks if affinity doesn't allow it
authorChris Redpath <chris.redpath@arm.com>
Mon, 24 Mar 2014 13:47:30 +0000 (13:47 +0000)
committerJon Medhurst <tixy@linaro.org>
Mon, 24 Mar 2014 15:14:35 +0000 (15:14 +0000)
When looking for a task to be idle-pulled, don't consider tasks
where the affinity does not allow that task to be placed on the
target CPU. Also ensure that tasks with restricted affinity
do not block selecting other unrestricted busy tasks.

Use the knowledge of target CPU more effectively in idle pull
by passing to hmp_get_heaviest_task when we know it, otherwise
only checking for general affinity matches with any of the CPUs
in the bigger HMP domain.

We still need to explicitly check affinity is allowed in idle pull
since if we find no match in hmp_get_heaviest_task we will return
the current one, which may not be affine to the new CPU despite
having high enough load. In this case, there is nothing to move.

Signed-off-by: Chris Redpath <chris.redpath@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
kernel/sched/fair.c

index 128d5723ae4d301c593ddb7c29e81fe89f423726..1957f2589d9a0728515fd8313f32fa8d4901481f 100644 (file)
@@ -3694,30 +3694,31 @@ static inline struct hmp_domain *hmp_faster_domain(int cpu);
 
 /* must hold runqueue lock for queue se is currently on */
 static struct sched_entity *hmp_get_heaviest_task(
-                               struct sched_entity *se, int migrate_up)
+                               struct sched_entity *se, int target_cpu)
 {
        int num_tasks = hmp_max_tasks;
        struct sched_entity *max_se = se;
        unsigned long int max_ratio = se->avg.load_avg_ratio;
        const struct cpumask *hmp_target_mask = NULL;
+       struct hmp_domain *hmp;
 
-       if (migrate_up) {
-               struct hmp_domain *hmp;
-               if (hmp_cpu_is_fastest(cpu_of(se->cfs_rq->rq)))
-                       return max_se;
+       if (hmp_cpu_is_fastest(cpu_of(se->cfs_rq->rq)))
+               return max_se;
 
-               hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq));
-               hmp_target_mask = &hmp->cpus;
+       hmp = hmp_faster_domain(cpu_of(se->cfs_rq->rq));
+       hmp_target_mask = &hmp->cpus;
+       if (target_cpu >= 0) {
+               BUG_ON(!cpumask_test_cpu(target_cpu, hmp_target_mask));
+               hmp_target_mask = cpumask_of(target_cpu);
        }
        /* The currently running task is not on the runqueue */
        se = __pick_first_entity(cfs_rq_of(se));
 
        while (num_tasks && se) {
                if (entity_is_task(se) &&
-                       (se->avg.load_avg_ratio > max_ratio &&
-                        hmp_target_mask &&
-                        cpumask_intersects(hmp_target_mask,
-                               tsk_cpus_allowed(task_of(se))))) {
+                       se->avg.load_avg_ratio > max_ratio &&
+                       cpumask_intersects(hmp_target_mask,
+                               tsk_cpus_allowed(task_of(se)))) {
                        max_se = se;
                        max_ratio = se->avg.load_avg_ratio;
                }
@@ -7126,7 +7127,7 @@ static void hmp_force_up_migration(int this_cpu)
                        }
                }
                orig = curr;
-               curr = hmp_get_heaviest_task(curr, 1);
+               curr = hmp_get_heaviest_task(curr, -1);
                p = task_of(curr);
                if (hmp_up_migration(cpu, &target_cpu, curr)) {
                        cpu_rq(target_cpu)->wake_for_idle_pull = 1;
@@ -7223,12 +7224,14 @@ static unsigned int hmp_idle_pull(int this_cpu)
                        }
                }
                orig = curr;
-               curr = hmp_get_heaviest_task(curr, 1);
+               curr = hmp_get_heaviest_task(curr, this_cpu);
                /* check if heaviest eligible task on this
                 * CPU is heavier than previous task
                 */
                if (hmp_task_eligible_for_up_migration(curr) &&
-                       curr->avg.load_avg_ratio > ratio) {
+                       curr->avg.load_avg_ratio > ratio &&
+                       cpumask_test_cpu(this_cpu,
+                                       tsk_cpus_allowed(task_of(curr)))) {
                        p = task_of(curr);
                        target = rq;
                        ratio = curr->avg.load_avg_ratio;