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.
Showing the changes to kernel (3 of 3 files). Show all
Unified · Split
| @@ -2733,15 +2733,17 @@ static int balance_dl(struct rq *rq, struct rq_flags *rf) · 2732 unmodified lines | |||
| 2733 | */ | 2733 | */ |
| 2734 | static void wakeup_preempt_dl(struct rq *rq, struct task_struct *p, int flags) | 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 | * Can only get preempted by stop-class, and those should be | 2738 | * Can only get preempted by stop-class, and those should be |
| 2738 | * few and short lived, doesn't really make sense to push | 2739 | * few and short lived, doesn't really make sense to push |
| 2739 | * anything away for that. | 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 | return; | 2744 | return; |
| 2743 | 2745 | ||
| 2744 | if (dl_entity_preempt(&p->dl, &rq->donor->dl)) { | 2746 | if (dl_entity_preempt(&p->dl, &donor->dl)) { |
| 2745 | resched_curr(rq); | 2747 | resched_curr(rq); |
| 2746 | return; | 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 | * XXX Getting preempted by higher class, try and find idle CPU? | 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 | return; | 9783 | return; |
| 9783 | 9784 | ||
| 9784 | if (unlikely(se == pse)) | 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 | * XXX If we're preempted by DL, queue a push? | 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 | return; | 1634 | return; |
| 1634 | 1635 | ||
| 1635 | if (p->prio < donor->prio) { | 1636 | if (p->prio < donor->prio) { |