diff options
author | Dietmar Eggemann <dietmar.eggemann@arm.com> | 2014-01-16 11:53:14 +0000 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2014-01-22 09:50:46 +0000 |
commit | b30814c74c184bbb231e24d6c857699af338468b (patch) | |
tree | e3e8edd21f41c2f45516edbf2d1ccfa18dba75db | |
parent | 1d462599bee9a2f5f3988aafa43feda602d5e188 (diff) |
HMP: Fix rt task allowed cpu mask restriction code on 1x1 systembig-LITTLE-MP-14.03big-LITTLE-MP-14.02big-LITTLE-MP-14.01
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>
-rw-r--r-- | kernel/sched/core.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index fb9b7b74a83..3e326f9208f 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3842,8 +3842,11 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) p->sched_class = &rt_sched_class; #ifdef CONFIG_SCHED_HMP 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 |