Messages in this thread Patch in this message | | | From | Daniel Bristot de Oliveira <> | Subject | [PATCH 5/6] sched/deadline: Add helpers to get the correct root domain/span/dl_bw | Date | Tue, 12 Jan 2021 16:53:44 +0100 |
| |
task_cpu() is often used on SCHED_DEADLINE to access the root_domain and associated information. However, the task_cpu() does not always reflect the correct CPU. The reason being is shown in the code:
From kernel/sched/core: ----- %< ----- * p->on_rq <- { 0, 1 = TASK_ON_RQ_QUEUED, 2 = TASK_ON_RQ_MIGRATING }: * * is set by activate_task() and cleared by deactivate_task(), under * rq->lock. Non-zero indicates the task is runnable, the special * ON_RQ_MIGRATING state is used for migration without holding both * rq->locks. It indicates task_cpu() is not stable, see task_rq_lock(). [...] * task_cpu(p): is changed by set_task_cpu(), the rules are: * * - Don't call set_task_cpu() on a blocked task: * * We don't care what CPU we're not running on, this simplifies hotplug, * the CPU assignment of blocked tasks isn't required to be valid. ----- >% -----
So, a sleeping task will not have its task_cpu() stable, and this is causing problems on SCHED_DEADLINE.
In preparation for fixing this problems, we need to add helper functions that return the dl_task_cpu, root_domain, and "root" dl_bw that reflects the current placement/affinity of the task.
Note that these functions are only required on the code path that can happen when the task is not queued.
Signed-off-by: Daniel Bristot de Oliveira <bristot@redhat.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Vincent Guittot <vincent.guittot@linaro.org> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Ben Segall <bsegall@google.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Daniel Bristot de Oliveira <bristot@redhat.com> Cc: Li Zefan <lizefan@huawei.com> Cc: Tejun Heo <tj@kernel.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Valentin Schneider <valentin.schneider@arm.com> Cc: linux-kernel@vger.kernel.org Cc: cgroups@vger.kernel.org --- kernel/sched/sched.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+)
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 54881d99cebd..5f3f3cb5a6ff 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2393,6 +2393,37 @@ void __dl_update(struct dl_bw *dl_b, s64 bw) rq->dl.extra_bw += bw; } } + +static inline +int dl_task_cpu(struct task_struct *p) +{ + /* + * We can only rely on task_cpu() of runnable tasks. + */ + if (p->on_rq) + return task_cpu(p); + + /* + * The task_cpu() of non-runnable task migth be pointing a CPU + * it cannot run anymore (see set_task_cpu()). Hence, let's + * get a possible cpu from the current cpu_mask. + */ + return cpumask_any(p->cpus_ptr); + +} + +static inline +struct root_domain *dl_task_rd(struct task_struct *p) +{ + int cpu = dl_task_cpu(p); + return cpu_rq(cpu)->rd; +} + +static inline +struct dl_bw *dl_task_root_bw(struct task_struct *p) +{ + return &dl_task_rd(p)->dl_bw; +} #else static inline void __dl_update(struct dl_bw *dl_b, s64 bw) @@ -2401,6 +2432,18 @@ void __dl_update(struct dl_bw *dl_b, s64 bw) dl->extra_bw += bw; } + +static inline +int dl_task_cpu(struct task_struct *p) +{ + return 0; +} + +static inline +struct dl_bw *dl_task_root_bw(struct task_struct *p) +{ + return &task_rq(p)->dl.dl_bw; +} #endif -- 2.29.2
| |