The reason for the clause in try_to_wake_up() is, per its comment, that find_proxy_task()'s proxy_deactivate() is not always called with a cleared p->blocked_on. However, that seems silly and easily cured. Make sure to always call proxy_deactivate() with a cleared p->blocked_on such that we might remove this clause from the common wake-up path.
Unified · Split
| @@ -4343,14 +4343,6 @@ int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) · 4342 unmodified lines | ||
| 4343 | 4343 | */ |
| 4344 | 4344 | WRITE_ONCE(p->__state, TASK_WAKING); |
| 4345 | 4345 | |
| 4346 | − /* | |
| 4347 | − * We never clear the blocked_on relation on proxy_deactivate. | |
| 4348 | − * If we don't clear it here, we have TASK_RUNNING + p->blocked_on | |
| 4349 | − * when waking up. Since this is a fully blocked, off CPU task | |
| 4350 | − * waking up, it should be safe to clear the blocked_on relation. | |
| 4351 | − */ | |
| 4352 | − if (task_is_blocked(p)) | |
| 4353 | − clear_task_blocked_on(p, NULL); | |
| 4354 | 4346 | /* |
| 4355 | 4347 | * If the owning (remote) CPU is still in the middle of schedule() with |
| 4356 | 4348 | * this task as prev, considering queueing p on the remote CPUs wake_list |
| @@ -6739,6 +6731,7 @@ static void proxy_deactivate(struct rq *rq, struct task_struct *donor) · 2382 unmodified lines | ||
| 6739 | 6731 | unsigned long state = READ_ONCE(donor->__state); |
| 6740 | 6732 | |
| 6741 | 6733 | WARN_ON_ONCE(state == TASK_RUNNING); |
| 6734 | + WARN_ON_ONCE(donor->blocked_on); | |
| 6742 | 6735 | /* |
| 6743 | 6736 | * Because we got donor from pick_next_task(), it is *crucial* |
| 6744 | 6737 | * that we call proxy_resched_idle() before we deactivate it. |
| @@ -6864,9 +6857,9 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 119 unmodified lines | ||
| 6864 | 6857 | for (p = donor; (mutex = p->blocked_on); p = owner) { |
| 6865 | 6858 | /* if its PROXY_WAKING, do return migration or run if current */ |
| 6866 | 6859 | if (mutex == PROXY_WAKING) { |
| 6860 | + clear_task_blocked_on(p, PROXY_WAKING); | |
| 6867 | 6861 | if (task_current(rq, p)) { |
| 6868 | 6862 | p->is_blocked = 0; |
| 6869 | − clear_task_blocked_on(p, PROXY_WAKING); | |
| 6870 | 6863 | return p; |
| 6871 | 6864 | } |
| 6872 | 6865 | goto deactivate; |
| @@ -6900,9 +6893,9 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 27 unmodified lines | ||
| 6900 | 6893 | * and return p (if it is current and safe to |
| 6901 | 6894 | * just run on this rq), or return-migrate the task. |
| 6902 | 6895 | */ |
| 6896 | + __clear_task_blocked_on(p, NULL); | |
| 6903 | 6897 | if (task_current(rq, p)) { |
| 6904 | 6898 | p->is_blocked = 0; |
| 6905 | − __clear_task_blocked_on(p, NULL); | |
| 6906 | 6899 | return p; |
| 6907 | 6900 | } |
| 6908 | 6901 | goto deactivate; |
| @@ -6912,6 +6905,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 3 unmodified lines | ||
| 6912 | 6905 | /* XXX Don't handle blocked owners/delayed dequeue yet */ |
| 6913 | 6906 | if (curr_in_chain) |
| 6914 | 6907 | return proxy_resched_idle(rq); |
| 6908 | + __clear_task_blocked_on(p, NULL); | |
| 6915 | 6909 | goto deactivate; |
| 6916 | 6910 | } |
| 6917 | 6911 | |