| From 2a84b34503ad7c1ef36e77890b5d6766aa776590 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 14 Jan 2020 15:13:56 +0100 |
| Subject: sched/fair: Prevent unlimited runtime on throttled group |
| |
| From: Vincent Guittot <vincent.guittot@linaro.org> |
| |
| [ Upstream commit 2a4b03ffc69f2dedc6388e9a6438b5f4c133a40d ] |
| |
| When a running task is moved on a throttled task group and there is no |
| other task enqueued on the CPU, the task can keep running using 100% CPU |
| whatever the allocated bandwidth for the group and although its cfs rq is |
| throttled. Furthermore, the group entity of the cfs_rq and its parents are |
| not enqueued but only set as curr on their respective cfs_rqs. |
| |
| We have the following sequence: |
| |
| sched_move_task |
| -dequeue_task: dequeue task and group_entities. |
| -put_prev_task: put task and group entities. |
| -sched_change_group: move task to new group. |
| -enqueue_task: enqueue only task but not group entities because cfs_rq is |
| throttled. |
| -set_next_task : set task and group_entities as current sched_entity of |
| their cfs_rq. |
| |
| Another impact is that the root cfs_rq runnable_load_avg at root rq stays |
| null because the group_entities are not enqueued. This situation will stay |
| the same until an "external" event triggers a reschedule. Let trigger it |
| immediately instead. |
| |
| Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Acked-by: Ben Segall <bsegall@google.com> |
| Link: https://lkml.kernel.org/r/1579011236-31256-1-git-send-email-vincent.guittot@linaro.org |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| kernel/sched/core.c | 9 ++++++++- |
| 1 file changed, 8 insertions(+), 1 deletion(-) |
| |
| diff --git a/kernel/sched/core.c b/kernel/sched/core.c |
| index 65ed821335dd5..9e7768dbd92d2 100644 |
| --- a/kernel/sched/core.c |
| +++ b/kernel/sched/core.c |
| @@ -7068,8 +7068,15 @@ void sched_move_task(struct task_struct *tsk) |
| |
| if (queued) |
| enqueue_task(rq, tsk, queue_flags); |
| - if (running) |
| + if (running) { |
| set_next_task(rq, tsk); |
| + /* |
| + * After changing group, the running task may have joined a |
| + * throttled one but it's still the running task. Trigger a |
| + * resched to make sure that task can still run. |
| + */ |
| + resched_curr(rq); |
| + } |
| |
| task_rq_unlock(rq, tsk, &rf); |
| } |
| -- |
| 2.20.1 |
| |