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 <satyap@codeaurora.org>
This commit is contained in:
Satya Durga Srinivasu Prabhala 2021-05-19 08:41:38 -07:00 committed by Rishabh Bhatnagar
parent 5f5bd6a0d2
commit 7d53585557
3 changed files with 19 additions and 10 deletions

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}