The way wakeup_preempt() works since commit 704069649b5b ("sched/core: Rework sched_class::wakeup_preempt() and rq_modified_*()") is that it will call rq->next_class->wakeup_preempt(rq, p) when p is of an equal or higher class, and raise ->next_class when higher. This means that: running idle task wakeup fair-A (next_class == idle) if (sched_class_above(fair, idle)) { wakeup_preempt_idle(fair-A); resched_curr(rq); next_class = fair; } wakeup fair-B (next_class == fair) if (fair == fair) wakeup_preempt_fair(fair-B); (but current is idle) All wakeup_preempt_$class() methods, except for wakeup_preempt_scx() (for whoem this was build) ignore cross-class wakeups by testing if @p is of the right class, but per the above case, it also should check current. This is mostly harmless in the current form, but will lead to trouble with later patches.
Unified · Split
| @@ -2733,15 +2733,17 @@ static int balance_dl(struct rq *rq, struct rq_flags *rf) · 2732 unmodified lines | ||
| 2733 | 2733 | */ |
| 2734 | 2734 | static void wakeup_preempt_dl(struct rq *rq, struct task_struct *p, int flags) |
| 2735 | 2735 | { |
| 2736 | + struct task_struct *donor = rq->donor; | |
| 2736 | 2737 | /* |
| 2737 | 2738 | * Can only get preempted by stop-class, and those should be |
| 2738 | 2739 | * few and short lived, doesn't really make sense to push |
| 2739 | 2740 | * anything away for that. |
| 2740 | 2741 | */ |
| 2741 | − if (p->sched_class != &dl_sched_class) | |
| 2742 | + if (p->sched_class != &dl_sched_class || | |
| 2743 | + donor->sched_class != &dl_sched_class) | |
| 2742 | 2744 | return; |
| 2743 | 2745 | |
| 2744 | − if (dl_entity_preempt(&p->dl, &rq->donor->dl)) { | |
| 2746 | + if (dl_entity_preempt(&p->dl, &donor->dl)) { | |
| 2745 | 2747 | resched_curr(rq); |
| 2746 | 2748 | return; |
| 2747 | 2749 | } |
| @@ -9778,7 +9778,8 @@ static void wakeup_preempt_fair(struct rq *rq, struct task_struct *p, int wake_f · 9777 unmodified lines | ||
| 9778 | 9778 | /* |
| 9779 | 9779 | * XXX Getting preempted by higher class, try and find idle CPU? |
| 9780 | 9780 | */ |
| 9781 | − if (p->sched_class != &fair_sched_class) | |
| 9781 | + if (p->sched_class != &fair_sched_class || | |
| 9782 | + donor->sched_class != &fair_sched_class) | |
| 9782 | 9783 | return; |
| 9783 | 9784 | |
| 9784 | 9785 | if (unlikely(se == pse)) |
| @@ -1629,7 +1629,8 @@ static void wakeup_preempt_rt(struct rq *rq, struct task_struct *p, int flags) · 1628 unmodified lines | ||
| 1629 | 1629 | /* |
| 1630 | 1630 | * XXX If we're preempted by DL, queue a push? |
| 1631 | 1631 | */ |
| 1632 | − if (p->sched_class != &rt_sched_class) | |
| 1632 | + if (p->sched_class != &rt_sched_class || | |
| 1633 | + donor->sched_class != &rt_sched_class) | |
| 1633 | 1634 | return; |
| 1634 | 1635 | |
| 1635 | 1636 | if (p->prio < donor->prio) { |