From dc23aae552c1579a8eb258ade569814544e8a745 Mon Sep 17 00:00:00 2001 From: Pavankumar Kondeti Date: Tue, 27 Apr 2021 16:21:11 +0530 Subject: [PATCH] sched: walt: Fix stale walt CPU reservation flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CPU trying to move a task to other cpu in active load balance or by other means, then the other helping cpu marked as reserved to avoid it for other scheduler decisions. Once the task moved successfully, the reservation will be cleared enables for other scheduler decisions. The reserved flag is been analogously protected with busy cpu’s rq->active_balance, which is protected with runqueue locks. So whenever rq->active_balance is set for busy cpu, then reserved flag would set for helping cpu. Sometimes, it is observed that, cpu is marked as reserved with no cpu's rq->active_balance set. There are some unlikely possible corner cases may cause this behavior: - On active load balance path, cpu stop machine returns queued status of active_balance work on cpu_stopper, which is not checked on active balance path. so when stop machine is not able to queue ( unlikely), then reserved flag wouldn't be cleared. So, catch the return value and on failure, clear reserved flag for cpu. - Clear_walt_request() called on the cpu to clear any pending walt works, it may possible that, push_task might have changed or cleared, then reserved cpu would be left uncleared. So clear the push_cpu independent of push_task. Change-Id: I75d032bf399cb3da8e807186b1bc903114168a4e Signed-off-by: Pavankumar Kondeti Signed-off-by: Lingutla Chandrasekhar --- kernel/sched/fair.c | 9 ++++++++- kernel/sched/walt/walt.c | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 3e153cf21fe1..73caf93f23c0 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -10443,9 +10443,16 @@ no_move: raw_spin_unlock_irqrestore(&busiest->lock, flags); if (active_balance) { - stop_one_cpu_nowait(cpu_of(busiest), + int ret; + + ret = stop_one_cpu_nowait(cpu_of(busiest), active_load_balance_cpu_stop, busiest, &busiest->active_balance_work); + if (!ret) { + clear_reserved(this_cpu); + busiest->active_balance = 0; + active_balance = 0; + } *continue_balancing = 0; } diff --git a/kernel/sched/walt/walt.c b/kernel/sched/walt/walt.c index c130771c3dad..99e8a0bf78ab 100644 --- a/kernel/sched/walt/walt.c +++ b/kernel/sched/walt/walt.c @@ -500,10 +500,10 @@ void clear_walt_request(int cpu) raw_spin_lock_irqsave(&rq->lock, flags); if (rq->wrq.push_task) { - clear_reserved(rq->push_cpu); push_task = rq->wrq.push_task; rq->wrq.push_task = NULL; } + clear_reserved(rq->push_cpu); rq->active_balance = 0; raw_spin_unlock_irqrestore(&rq->lock, flags); if (push_task)