sched/walt: fix deadlock due to recursive rq locking

complete_all() being called from android_rvh_tick_entry()
trace hook implementation to wake up task (kworker) waiting
on completion variable.

While task waking if scheduler chooses to place the task on
same CPU where complete_all() is invoked (from scheduler_tick()),
system would run into deadlock as wake up path tries to acquire
rq lock of the CPU from ttwu_queue() which was already acquired
in scheduler_tick().

Fix the deadlock by moving related code chunk to
android_vh_scheduler_tick() trace hook implementation.

Call statck for info:
[<ffffffda02613964>] queued_spin_lock_slowpath+0x88
[<ffffffda025c94c0>] try_to_wake_up[jt]+0x25c
[<ffffffda025fbe0c>] complete_all+0xb4
[<ffffffd9fdb7635c>] android_rvh_tick_entry[sched_walt]+0x5c
[<ffffffda025d1bdc>] scheduler_tick+0x4b0

Fixes: 4e3e7cc6133d2f7 ("sched: Align window start with tick boundary")
Change-Id: I1e1310c6c5513f38c4fd95b933ff407d740c1112
Signed-off-by: Satya Durga Srinivasu Prabhala <quic_satyap@quicinc.com>
This commit is contained in:
Satya Durga Srinivasu Prabhala 2022-04-14 12:16:01 -07:00 committed by Rishabh Bhatnagar
parent 97a7eb4292
commit 318a435b83

View File

@ -4189,22 +4189,13 @@ static void android_rvh_try_to_wake_up_success(void *unused, struct task_struct
raw_spin_unlock_irqrestore(&cpu_rq(cpu)->__lock, flags);
}
u64 tick_sched_clock;
static u64 tick_sched_clock;
static DECLARE_COMPLETION(tick_sched_clock_completion);
static void android_rvh_tick_entry(void *unused, struct rq *rq)
{
u64 wallclock;
if (!tick_sched_clock) {
/*
* Let the window begin 20us prior to the tick,
* that way we are guaranteed a rollover when the tick occurs.
*/
tick_sched_clock = rq_clock(rq) - 20000;
complete_all(&tick_sched_clock_completion);
}
lockdep_assert_held(&rq->__lock);
if (unlikely(walt_disabled))
return;
@ -4222,6 +4213,15 @@ static void android_vh_scheduler_tick(void *unused, struct rq *rq)
struct walt_related_thread_group *grp;
u32 old_load;
if (!tick_sched_clock) {
/*
* Let the window begin 20us prior to the tick,
* that way we are guaranteed a rollover when the tick occurs.
*/
tick_sched_clock = rq_clock(rq) - 20000;
complete(&tick_sched_clock_completion);
}
if (unlikely(walt_disabled))
return;
@ -4442,7 +4442,7 @@ static void walt_init(struct work_struct *work)
walt_rt_init();
walt_cfs_init();
walt_halt_init();
wait_for_completion(&tick_sched_clock_completion);
wait_for_completion_interruptible(&tick_sched_clock_completion);
stop_machine(walt_init_stop_handler, NULL, NULL);
hdr = register_sysctl_table(walt_base_table);