summaryrefslogtreecommitdiff
path: root/kernel/sched/core.c
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2017-07-27 09:44:21 -0600
committerMathieu Poirier <mathieu.poirier@linaro.org>2018-02-13 11:06:30 -0700
commit261bfb980de275c305d608c90f6dd502dc9f9461 (patch)
tree76dff62aaded3ac4dceab96f753c4afea6ec2863 /kernel/sched/core.c
parent719ea98897fdae5b5e1c5fe8bb353ae87b8c687c (diff)
sched/deadline: Keep new DL task within root domain's boundary
When considering to move a task to the DL policy we need to make sure the CPUs it is allowed to run on matches the CPUs of the root domain of the runqueue it is currently assigned to. Otherwise the task will be allowed to roam on CPUs outside of this root domain, something that will skew system deadline statistics and potentially lead to over selling DL bandwidth. For example we have a system where the cpuset.sched_load_balance flag of the root cpuset has been set to 0 and the 4 core system split in 2 cpuset: set1 has CPU 0 and 1 while set2 has CPU 2 and 3. This results in 3 cpuset, i.e, the default set that has all 4 CPUs along with set1 and set2 as just depicted. We also have task A that hasn't been assigned to any CPUset and as such, is part of the default (root) CPUset. At the time we want to move task A to a DL policy it has been assigned to CPU1. Since CPU1 is part of set1 the root domain will have 2 CPUs in it and the bandwidth constraint checked against the current DL bandwidth allotment of those 2 CPUs. If task A is promoted to a DL policy it's 'cpus_allowed' mask is still equal to the CPUs in the default CPUset, making it possible for the scheduler to move it to CPU2 and CPU3, which could also be running DL tasks of their own. This patch makes sure that a task's cpus_allowed mask matches the CPUs of the root domain associated to the runqueue it has been assigned to. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Diffstat (limited to 'kernel/sched/core.c')
-rw-r--r--kernel/sched/core.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 0d8badcf1f0f..b930857f4d14 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4237,6 +4237,26 @@ change:
cpumask_t *span = rq->rd->span;
/*
+ * If setscheduling to SCHED_DEADLINE we need to make
+ * sure the task is constrained to run within the root
+ * domain it is associated with, something that isn't
+ * guaranteed when using cpusets.
+ *
+ * Speaking of cpusets, we also need to assert that a
+ * task's cpus_allowed mask equals its cpuset's
+ * cpus_allowed mask. Otherwise a DL task could be
+ * assigned to a cpuset that has more CPUs than the root
+ * domain it is associated with, a situation that yields
+ * no benefits and greatly complicate the management of
+ * DL task when cpusets are present.
+ */
+ if (!cpumask_equal(&p->cpus_allowed, span) ||
+ !cpuset_cpus_match_task(p)) {
+ retval = -EPERM;
+ goto unlock;
+ }
+
+ /*
* Don't allow tasks with an affinity mask smaller than
* the entire root_domain to become SCHED_DEADLINE. We
* will also fail if there's no bandwidth available.