@@ -3735,6 +3735,53 @@ void update_rq_avg_idle(struct rq *rq)
37353735 rq -> idle_stamp = 0 ;
37363736}
37373737
3738+ #ifdef CONFIG_SCHED_PROXY_EXEC
3739+ static void zap_balance_callbacks (struct rq * rq );
3740+
3741+ static inline void proxy_reset_donor (struct rq * rq )
3742+ {
3743+ WARN_ON_ONCE (rq -> donor == rq -> curr );
3744+
3745+ put_prev_set_next_task (rq , rq -> donor , rq -> curr );
3746+ rq_set_donor (rq , rq -> curr );
3747+ zap_balance_callbacks (rq );
3748+ resched_curr (rq );
3749+ }
3750+
3751+ /*
3752+ * Checks to see if task p has been proxy-migrated to another rq
3753+ * and needs to be returned. If so, we deactivate the task here
3754+ * so that it can be properly woken up on the p->wake_cpu
3755+ * (or whichever cpu select_task_rq() picks at the bottom of
3756+ * try_to_wake_up()
3757+ */
3758+ static inline bool proxy_needs_return (struct rq * rq , struct task_struct * p )
3759+ {
3760+ if (!task_is_blocked (p ))
3761+ return false;
3762+
3763+ scoped_guard (raw_spinlock , & p -> blocked_lock ) {
3764+ /* Task is waking up; clear any blocked_on relationship */
3765+ __clear_task_blocked_on (p , NULL );
3766+
3767+ /* If already current, don't need to return migrate */
3768+ if (task_current (rq , p ))
3769+ return false;
3770+
3771+ /* If we're return migrating the rq->donor, switch it out for idle */
3772+ if (task_current_donor (rq , p ))
3773+ proxy_reset_donor (rq );
3774+ }
3775+ block_task (rq , p , TASK_WAKING );
3776+ return true;
3777+ }
3778+ #else /* !CONFIG_SCHED_PROXY_EXEC */
3779+ static inline bool proxy_needs_return (struct rq * rq , struct task_struct * p )
3780+ {
3781+ return false;
3782+ }
3783+ #endif /* CONFIG_SCHED_PROXY_EXEC */
3784+
37383785static void
37393786ttwu_do_activate (struct rq * rq , struct task_struct * p , int wake_flags ,
37403787 struct rq_flags * rf )
@@ -3799,28 +3846,26 @@ ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags,
37993846 */
38003847static int ttwu_runnable (struct task_struct * p , int wake_flags )
38013848{
3802- struct rq_flags rf ;
3803- struct rq * rq ;
3804- int ret = 0 ;
3849+ ACQUIRE (__task_rq_lock , guard )(p );
3850+ struct rq * rq = guard .rq ;
38053851
3806- rq = __task_rq_lock (p , & rf );
3807- if (task_on_rq_queued (p )) {
3808- update_rq_clock (rq );
3809- if (p -> se .sched_delayed )
3810- enqueue_task (rq , p , ENQUEUE_NOCLOCK | ENQUEUE_DELAYED );
3811- if (!task_on_cpu (rq , p )) {
3812- /*
3813- * When on_rq && !on_cpu the task is preempted, see if
3814- * it should preempt the task that is current now.
3815- */
3816- wakeup_preempt (rq , p , wake_flags );
3817- }
3818- ttwu_do_wakeup (p );
3819- ret = 1 ;
3820- }
3821- __task_rq_unlock (rq , p , & rf );
3852+ if (!task_on_rq_queued (p ))
3853+ return 0 ;
38223854
3823- return ret ;
3855+ update_rq_clock (rq );
3856+ if (p -> se .sched_delayed )
3857+ enqueue_task (rq , p , ENQUEUE_NOCLOCK | ENQUEUE_DELAYED );
3858+ if (proxy_needs_return (rq , p ))
3859+ return 0 ;
3860+ if (!task_on_cpu (rq , p )) {
3861+ /*
3862+ * When on_rq && !on_cpu the task is preempted, see if
3863+ * it should preempt the task that is current now.
3864+ */
3865+ wakeup_preempt (rq , p , wake_flags );
3866+ }
3867+ ttwu_do_wakeup (p );
3868+ return 1 ;
38243869}
38253870
38263871void sched_ttwu_pending (void * arg )
@@ -4207,6 +4252,8 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
42074252 * it disabling IRQs (this allows not taking ->pi_lock).
42084253 */
42094254 WARN_ON_ONCE (p -> se .sched_delayed );
4255+ /* If p is current, we know we can run here, so clear blocked_on */
4256+ clear_task_blocked_on (p , NULL );
42104257 if (!ttwu_state_match (p , state , & success ))
42114258 goto out ;
42124259
@@ -4223,6 +4270,7 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
42234270 */
42244271 scoped_guard (raw_spinlock_irqsave , & p -> pi_lock ) {
42254272 smp_mb__after_spinlock ();
4273+
42264274 if (!ttwu_state_match (p , state , & success ))
42274275 break ;
42284276
@@ -4287,6 +4335,14 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
42874335 */
42884336 WRITE_ONCE (p -> __state , TASK_WAKING );
42894337
4338+ /*
4339+ * We never clear the blocked_on relation on proxy_deactivate.
4340+ * If we don't clear it here, we have TASK_RUNNING + p->blocked_on
4341+ * when waking up. Since this is a fully blocked, off CPU task
4342+ * waking up, it should be safe to clear the blocked_on relation.
4343+ */
4344+ if (task_is_blocked (p ))
4345+ clear_task_blocked_on (p , NULL );
42904346 /*
42914347 * If the owning (remote) CPU is still in the middle of schedule() with
42924348 * this task as prev, considering queueing p on the remote CPUs wake_list
@@ -4331,6 +4387,16 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
43314387 wake_flags |= WF_MIGRATED ;
43324388 psi_ttwu_dequeue (p );
43334389 set_task_cpu (p , cpu );
4390+ } else if (cpu != p -> wake_cpu ) {
4391+ /*
4392+ * If we were proxy-migrated to cpu, then
4393+ * select_task_rq() picks cpu instead of wake_cpu
4394+ * to return to, we won't call set_task_cpu(),
4395+ * leaving a stale wake_cpu pointing to where we
4396+ * proxy-migrated from. So just fixup wake_cpu here
4397+ * if its not correct
4398+ */
4399+ p -> wake_cpu = cpu ;
43344400 }
43354401
43364402 ttwu_queue (p , cpu , wake_flags );
@@ -6612,7 +6678,7 @@ static bool try_to_block_task(struct rq *rq, struct task_struct *p,
66126678 if (signal_pending_state (task_state , p )) {
66136679 WRITE_ONCE (p -> __state , TASK_RUNNING );
66146680 * task_state_p = TASK_RUNNING ;
6615- set_task_blocked_on_waking (p , NULL );
6681+ clear_task_blocked_on (p , NULL );
66166682
66176683 return false;
66186684 }
@@ -6656,13 +6722,11 @@ static inline struct task_struct *proxy_resched_idle(struct rq *rq)
66566722 return rq -> idle ;
66576723}
66586724
6659- static bool proxy_deactivate (struct rq * rq , struct task_struct * donor )
6725+ static void proxy_deactivate (struct rq * rq , struct task_struct * donor )
66606726{
66616727 unsigned long state = READ_ONCE (donor -> __state );
66626728
6663- /* Don't deactivate if the state has been changed to TASK_RUNNING */
6664- if (state == TASK_RUNNING )
6665- return false;
6729+ WARN_ON_ONCE (state == TASK_RUNNING );
66666730 /*
66676731 * Because we got donor from pick_next_task(), it is *crucial*
66686732 * that we call proxy_resched_idle() before we deactivate it.
@@ -6673,7 +6737,7 @@ static bool proxy_deactivate(struct rq *rq, struct task_struct *donor)
66736737 * need to be changed from next *before* we deactivate.
66746738 */
66756739 proxy_resched_idle (rq );
6676- return try_to_block_task (rq , donor , & state , true );
6740+ block_task (rq , donor , state );
66776741}
66786742
66796743static inline void proxy_release_rq_lock (struct rq * rq , struct rq_flags * rf )
@@ -6747,71 +6811,6 @@ static void proxy_migrate_task(struct rq *rq, struct rq_flags *rf,
67476811 proxy_reacquire_rq_lock (rq , rf );
67486812}
67496813
6750- static void proxy_force_return (struct rq * rq , struct rq_flags * rf ,
6751- struct task_struct * p )
6752- __must_hold (__rq_lockp (rq ))
6753- {
6754- struct rq * task_rq , * target_rq = NULL ;
6755- int cpu , wake_flag = WF_TTWU ;
6756-
6757- lockdep_assert_rq_held (rq );
6758- WARN_ON (p == rq -> curr );
6759-
6760- if (p == rq -> donor )
6761- proxy_resched_idle (rq );
6762-
6763- proxy_release_rq_lock (rq , rf );
6764- /*
6765- * We drop the rq lock, and re-grab task_rq_lock to get
6766- * the pi_lock (needed for select_task_rq) as well.
6767- */
6768- scoped_guard (task_rq_lock , p ) {
6769- task_rq = scope .rq ;
6770-
6771- /*
6772- * Since we let go of the rq lock, the task may have been
6773- * woken or migrated to another rq before we got the
6774- * task_rq_lock. So re-check we're on the same RQ. If
6775- * not, the task has already been migrated and that CPU
6776- * will handle any futher migrations.
6777- */
6778- if (task_rq != rq )
6779- break ;
6780-
6781- /*
6782- * Similarly, if we've been dequeued, someone else will
6783- * wake us
6784- */
6785- if (!task_on_rq_queued (p ))
6786- break ;
6787-
6788- /*
6789- * Since we should only be calling here from __schedule()
6790- * -> find_proxy_task(), no one else should have
6791- * assigned current out from under us. But check and warn
6792- * if we see this, then bail.
6793- */
6794- if (task_current (task_rq , p ) || task_on_cpu (task_rq , p )) {
6795- WARN_ONCE (1 , "%s rq: %i current/on_cpu task %s %d on_cpu: %i\n" ,
6796- __func__ , cpu_of (task_rq ),
6797- p -> comm , p -> pid , p -> on_cpu );
6798- break ;
6799- }
6800-
6801- update_rq_clock (task_rq );
6802- deactivate_task (task_rq , p , DEQUEUE_NOCLOCK );
6803- cpu = select_task_rq (p , p -> wake_cpu , & wake_flag );
6804- set_task_cpu (p , cpu );
6805- target_rq = cpu_rq (cpu );
6806- clear_task_blocked_on (p , NULL );
6807- }
6808-
6809- if (target_rq )
6810- attach_one_task (target_rq , p );
6811-
6812- proxy_reacquire_rq_lock (rq , rf );
6813- }
6814-
68156814/*
68166815 * Find runnable lock owner to proxy for mutex blocked donor
68176816 *
@@ -6847,7 +6846,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
68476846 clear_task_blocked_on (p , PROXY_WAKING );
68486847 return p ;
68496848 }
6850- goto force_return ;
6849+ goto deactivate ;
68516850 }
68526851
68536852 /*
@@ -6882,7 +6881,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
68826881 __clear_task_blocked_on (p , NULL );
68836882 return p ;
68846883 }
6885- goto force_return ;
6884+ goto deactivate ;
68866885 }
68876886
68886887 if (!READ_ONCE (owner -> on_rq ) || owner -> se .sched_delayed ) {
@@ -6961,12 +6960,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf)
69616960 return owner ;
69626961
69636962deactivate :
6964- if (proxy_deactivate (rq , donor ))
6965- return NULL ;
6966- /* If deactivate fails, force return */
6967- p = donor ;
6968- force_return :
6969- proxy_force_return (rq , rf , p );
6963+ proxy_deactivate (rq , p );
69706964 return NULL ;
69716965migrate_task :
69726966 proxy_migrate_task (rq , rf , p , owner_cpu );
@@ -7113,6 +7107,9 @@ static void __sched notrace __schedule(int sched_mode)
71137107 if (sched_proxy_exec ()) {
71147108 struct task_struct * prev_donor = rq -> donor ;
71157109
7110+ if (!prev_state && prev -> blocked_on )
7111+ clear_task_blocked_on (prev , NULL );
7112+
71167113 rq_set_donor (rq , next );
71177114 if (unlikely (next -> blocked_on )) {
71187115 next = find_proxy_task (rq , next , & rf );
0 commit comments