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: e4239ea599 ("ANDROID: sched: Handle blocked-waiter migration (and return migration)")
Change-Id: Id21c810b240d54aafc63bd0c34255eabdbefe94a
Reported-by: kuyo chang <kuyo.chang@mediatek.com>
Suggested-by: kuyo chang <kuyo.chang@mediatek.com>
Signed-off-by: John Stultz <jstultz@google.com>
This commit is contained in:
John Stultz
2025-01-21 12:01:23 -08:00
committed by Treehugger Robot
parent 9384a0909f
commit d9f67873f8
+14 -2
View File
@@ -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;
}