HMP: Fix rt task allowed cpu mask restriction code on 1x1 system
authorDietmar Eggemann <dietmar.eggemann@arm.com>
Wed, 4 Feb 2015 05:50:24 +0000 (14:50 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 14 Dec 2016 04:41:57 +0000 (13:41 +0900)
There is an error scenario where on a 1x1 HMP system (weight of the
hmp_slow_cpu_mask is 1) the short-cut of restricting the
allowed cpu mask
of an rt tasks leads to triggering a kernel bug in the rt sched class
set_cpus_allowed function set_cpus_allowed_rt().

In case the task is on the run-queue and the weight of the required cpu mask
is 1 and this is different to the p->nr_cpus_allowed value, this back-end
function interprets this in such a way that a task changed from being
migratable to not migratable anymore and decrements the rt_nr_migratory
counter.  There is a BUG_ON(!rq->rt.rt_nr_migratory) check in this code
path which triggers in this situation.

To circumvent this issue, set the number of allowed cpus for a task p to
the weight of the hmp_slow_cpu_mask before calling do_set_cpus_allowed()
in __setscheduler(). It will be set to this value in
do_set_cpus_allowed()
after the call to the sched class related backend function any way.  By
doing this, set_cpus_allowed_rt() returns without trying to update the
rt_nr_migratory counter.

This patch has been tested with a test device driver requiring a
threaded
irq handler on a TC2 system with a reduced cpu mask (1 Cortex A15, 1
Cortex A7).

Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
kernel/sched/core.c

index 7a00317..134c531 100644 (file)
@@ -3366,8 +3366,11 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
                if (cpumask_equal(&p->cpus_allowed, cpu_all_mask))
                        do_set_cpus_allowed(p, &hmp_slow_cpu_mask);
                if (!cpumask_empty(&hmp_slow_cpu_mask))
-                       if (cpumask_equal(&p->cpus_allowed, cpu_all_mask))
+                       if (cpumask_equal(&p->cpus_allowed, cpu_all_mask)) {
+                               p->nr_cpus_allowed =
+                                       cpumask_weight(&hmp_slow_cpu_mask);
                                do_set_cpus_allowed(p, &hmp_slow_cpu_mask);
+                       }
 #endif
        } else
                p->sched_class = &fair_sched_class;