From d9f67873f80b0ea18e39b6efa9c66db323e5ad04 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 Jan 2025 12:01:23 -0800 Subject: [PATCH] ANDROID: sched: Avoid re-evaluating proxy_needs_return when sched_proxy_exec() is disabled With proxy-execution, we add an extra check such that should the task have already been woken up, but it is still in the BO_WAKING state, thus potentially needed return-migration, we avoid breaking out of try_to_wakeup() in order so that the proxy_needs_return() logic in ttwu_runnable() can dequeue the task and allow it to be woken on its wake_cpu (effecively doing the return migration). As reported kuyo chang, this check is not conditionalized by sched_proxy_exec(), so when proxy-execution is disabled its possible for us to hit this case, and continue to ttwu_runnable(), however we won't do the proxy_needs_return() logic as it is conditionalized, resulting in the enqueued task being enqueued again, triggering warnings. WARNING: CPU: 5 PID: 20337 at kernel/sched/rt.c:1136 dequeue_rt_stack+0x1a0/0x26c Call trace: dequeue_rt_stack+0x1a0/0x26c enqueue_task_rt+0xa0/0x39c enqueue_task+0x7c/0x340 do_activate_task+0xcc/0x178 ttwu_do_activate+0xac/0x2a8 try_to_wake_up+0x748/0xb84 wake_up_q+0x70/0xd8 ... or WARNING: CPU: 6 PID: 0 at kernel/sched/rt.c:1823 pick_task_rt+0x98/0xb0 Call trace: pick_task_rt+0x98/0xb0 __schedule+0x494/0xc8c schedule_idle+0x24/0x48 do_idle+0x248/0x290 ... Thus, pull the check out to a separate function and include the check on sched_proxy_exec() so that it is properly conditionalized. Bug: 388983726 Fixes: e4239ea599c6 ("ANDROID: sched: Handle blocked-waiter migration (and return migration)") Change-Id: Id21c810b240d54aafc63bd0c34255eabdbefe94a Reported-by: kuyo chang Suggested-by: kuyo chang Signed-off-by: John Stultz --- kernel/sched/core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a444518f1930..270fbff836d7 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -3812,6 +3812,14 @@ static void do_activate_task(struct rq *rq, struct task_struct *p, int en_flags) raw_spin_unlock(&p->blocked_lock); } +static bool proxy_task_runnable_but_waking(struct task_struct *p) +{ + if (!sched_proxy_exec()) + return false; + return (READ_ONCE(p->__state) == TASK_RUNNING && + READ_ONCE(p->blocked_on_state) == BO_WAKING); +} + #ifdef CONFIG_SMP static inline void proxy_set_task_cpu(struct task_struct *p, int cpu) { @@ -4081,6 +4089,11 @@ static inline void do_activate_task(struct rq *rq, struct task_struct *p, activate_task(rq, p, en_flags); } +static bool proxy_task_runnable_but_waking(struct task_struct *p) +{ + return false; +} + static inline void activate_blocked_waiters(struct rq *target_rq, struct task_struct *owner, int wake_flags) @@ -4667,8 +4680,7 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) * continue on to ttwu_runnable check to force * proxy_needs_return evaluation */ - if (!(READ_ONCE(p->__state) == TASK_RUNNING && - READ_ONCE(p->blocked_on_state) == BO_WAKING)) + if (!proxy_task_runnable_but_waking(p)) break; }