summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDietmar Eggemann <dietmar.eggemann@arm.com>2015-02-04 14:50:24 +0900
committerSeung-Woo Kim <sw0312.kim@samsung.com>2016-12-14 13:41:57 +0900
commitf2ea79fb72c1a0b7ccdb09eb05715e2befa4eeba (patch)
tree4cace6f7f9d5c592ac1e121a19914c3b29455729 /kernel
parentee3cd3fbd1c45961722c64f7da8963c86ad8bd11 (diff)
HMP: Fix rt task allowed cpu mask restriction code on 1x1 system
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/core.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7a00317cbd56..134c531429be 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -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;