From 7d53585557f541ad826ce5ee6d2c18e7be18eb98 Mon Sep 17 00:00:00 2001 From: Satya Durga Srinivasu Prabhala Date: Wed, 19 May 2021 08:41:38 -0700 Subject: [PATCH] sched/walt: fix lock ordering issue between RTG lock and task's RQ lock lock ordering issue is observed in below scenario where preferred cluster for the task is being set on one CPU while task is being attached to related thread group which leads to deadlock. CPUX: scheduler_tick() --> acquire rq_lock() trace_android_rvh_tick_entry() android_rvh_tick_entry() set_preferred_cluster() --> try to acquire RTG lock taken by CPUY CPUY: cpu_cgroup_attach() trace_android_rvh_cpu_cgroup_attach() android_rvh_cpu_cgroup_attach() __sched_set_group_id() add_task_to_group() --> acquire RTG lock __task_rq_lock() --> try to acquire task's rq_lock() which is CPUX Fix the issue by moving set_preferred_cluster() related piece of code which is being called from scheduler_tick() to android_vh_scheduler_tick trace hook. Change-Id: Ib9e2d70ae45a304d21cde3de6b8a84f9049061ab Signed-off-by: Satya Durga Srinivasu Prabhala --- kernel/sched/walt/walt.c | 22 +++++++++++++++++----- kernel/sched/walt/walt.h | 1 + kernel/sched/walt/walt_lb.c | 6 +----- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/kernel/sched/walt/walt.c b/kernel/sched/walt/walt.c index 554fab2ee0a8..00a902f22626 100644 --- a/kernel/sched/walt/walt.c +++ b/kernel/sched/walt/walt.c @@ -3934,25 +3934,36 @@ static void android_rvh_try_to_wake_up_success(void *unused, struct task_struct static void android_rvh_tick_entry(void *unused, struct rq *rq) { u64 wallclock; - u32 old_load; - struct walt_related_thread_group *grp; + lockdep_assert_held(&rq->lock); if (unlikely(walt_disabled)) return; + set_window_start(rq); wallclock = sched_ktime_clock(); - old_load = task_load(rq->curr); walt_update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0); + if (is_ed_task_present(rq, wallclock, NULL)) + waltgov_run_callback(rq, WALT_CPUFREQ_EARLY_DET); +} + +static void android_vh_scheduler_tick(void *unused, struct rq *rq) +{ + struct walt_related_thread_group *grp; + u32 old_load; + + if (unlikely(walt_disabled)) + return; + + old_load = task_load(rq->curr); rcu_read_lock(); grp = task_related_thread_group(rq->curr); if (update_preferred_cluster(grp, rq->curr, old_load, true)) set_preferred_cluster(grp); rcu_read_unlock(); - if (is_ed_task_present(rq, wallclock, NULL)) - waltgov_run_callback(rq, WALT_CPUFREQ_EARLY_DET); + walt_lb_tick(rq); } static void android_rvh_schedule(void *unused, struct task_struct *prev, @@ -4081,6 +4092,7 @@ static void register_walt_hooks(void) register_trace_android_rvh_try_to_wake_up(android_rvh_try_to_wake_up, NULL); register_trace_android_rvh_try_to_wake_up_success(android_rvh_try_to_wake_up_success, NULL); register_trace_android_rvh_tick_entry(android_rvh_tick_entry, NULL); + register_trace_android_vh_scheduler_tick(android_vh_scheduler_tick, NULL); register_trace_android_rvh_schedule(android_rvh_schedule, NULL); register_trace_android_rvh_resume_cpus(android_rvh_resume_cpus, NULL); register_trace_android_rvh_cpu_cgroup_attach(android_rvh_cpu_cgroup_attach, NULL); diff --git a/kernel/sched/walt/walt.h b/kernel/sched/walt/walt.h index 43723dd53f8d..e4012126a0b7 100644 --- a/kernel/sched/walt/walt.h +++ b/kernel/sched/walt/walt.h @@ -881,5 +881,6 @@ static inline bool walt_fair_task(struct task_struct *p) void walt_cfs_enqueue_task(struct rq *rq, struct task_struct *p); void walt_cfs_dequeue_task(struct rq *rq, struct task_struct *p); void walt_cfs_tick(struct rq *rq); +void walt_lb_tick(struct rq *rq); #endif /* _WALT_H */ diff --git a/kernel/sched/walt/walt_lb.c b/kernel/sched/walt/walt_lb.c index a0adcd7d6cd4..547428bcf1b2 100644 --- a/kernel/sched/walt/walt_lb.c +++ b/kernel/sched/walt/walt_lb.c @@ -485,7 +485,7 @@ static int walt_lb_find_busiest_cpu(int dst_cpu, const cpumask_t *src_mask) } static DEFINE_RAW_SPINLOCK(walt_lb_migration_lock); -static void walt_lb_tick(void *unused, struct rq *rq) +void walt_lb_tick(struct rq *rq) { int prev_cpu = rq->cpu, new_cpu, ret; struct task_struct *p = rq->curr; @@ -493,9 +493,6 @@ static void walt_lb_tick(void *unused, struct rq *rq) struct walt_rq *wrq = (struct walt_rq *) rq->android_vendor_data1; struct walt_task_struct *wts = (struct walt_task_struct *) p->android_vendor_data1; - if (unlikely(walt_disabled)) - return; - if (!walt_fair_task(p)) return; @@ -842,5 +839,4 @@ void walt_lb_init(void) register_trace_android_rvh_can_migrate_task(walt_can_migrate_task, NULL); register_trace_android_rvh_find_busiest_queue(walt_find_busiest_queue, NULL); register_trace_android_rvh_sched_newidle_balance(walt_newidle_balance, NULL); - register_trace_android_vh_scheduler_tick(walt_lb_tick, NULL); }