Peter noted: Compilers are really bad (as in they utterly refuse) optimizing (even when marked with __pure) the static branch things, and will happily emit multiple identical in a row. So pull out the one obvious sched_proxy_exec() branch in __schedule() and remove some of the 'implicit' ones in that path.
Unified · Split
| @@ -6597,11 +6597,7 @@ find_proxy_task(struct rq *rq, struct task_struct *donor, struct rq_flags *rf) · 6596 unmodified lines | ||
| 6597 | 6597 | struct mutex *mutex; |
| 6598 | 6598 | |
| 6599 | 6599 | /* Follow blocked_on chain. */ |
| 6600 | − for (p = donor; task_is_blocked(p); p = owner) { | |
| 6601 | − mutex = p->blocked_on; | |
| 6602 | − /* Something changed in the chain, so pick again */ | |
| 6603 | − if (!mutex) | |
| 6604 | − return NULL; | |
| 6600 | + for (p = donor; (mutex = p->blocked_on); p = owner) { | |
| 6605 | 6601 | /* |
| 6606 | 6602 | * By taking mutex->wait_lock we hold off concurrent mutex_unlock() |
| 6607 | 6603 | * and ensure @owner sticks around. |
| @@ -6832,12 +6828,14 @@ pick_again: · 224 unmodified lines | ||
| 6832 | 6828 | next = pick_next_task(rq, rq->donor, &rf); |
| 6833 | 6829 | rq_set_donor(rq, next); |
| 6834 | 6830 | rq->next_class = next->sched_class; |
| 6835 | − if (unlikely(task_is_blocked(next))) { | |
| 6836 | − next = find_proxy_task(rq, next, &rf); | |
| 6837 | − if (!next) | |
| 6838 | − goto pick_again; | |
| 6839 | − if (next == rq->idle) | |
| 6840 | − goto keep_resched; | |
| 6831 | + if (sched_proxy_exec()) { | |
| 6832 | + if (unlikely(next->blocked_on)) { | |
| 6833 | + next = find_proxy_task(rq, next, &rf); | |
| 6834 | + if (!next) | |
| 6835 | + goto pick_again; | |
| 6836 | + if (next == rq->idle) | |
| 6837 | + goto keep_resched; | |
| 6838 | + } | |
| 6841 | 6839 | } |
| 6842 | 6840 | picked: |
| 6843 | 6841 | clear_tsk_need_resched(prev); |