]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
sched: Fix faulty assertion in sched_change_end()
authorPeter Zijlstra <peterz@infradead.org>
Wed, 17 Dec 2025 10:24:11 +0000 (11:24 +0100)
committerPeter Zijlstra <peterz@infradead.org>
Wed, 17 Dec 2025 10:41:18 +0000 (11:41 +0100)
Commit 47efe2ddccb1f ("sched/core: Add assertions to QUEUE_CLASS") added an
assert to sched_change_end() verifying that a class demotion would result in a
reschedule.

As it turns out; rt_mutex_setprio() does not force a resched on class
demontion. Furthermore, this is only relevant to running tasks.

Change the warning into a reschedule and make sure to only do so for running
tasks.

Fixes: 47efe2ddccb1f ("sched/core: Add assertions to QUEUE_CLASS")
Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Tested-by: Linux Kernel Functional Testing <lkft@linaro.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20251216141725.GW3707837@noisy.programming.kicks-ass.net
kernel/sched/core.c

index 7d0a862a8c75ca03b483c0edacb980b013d32d39..5b17d8e3cb55c6c881f424e5b73322fa2920c8bc 100644 (file)
@@ -10833,23 +10833,24 @@ void sched_change_end(struct sched_change_ctx *ctx)
                if (p->sched_class->switched_to)
                        p->sched_class->switched_to(rq, p);
 
-               /*
-                * If this was a class promotion; let the old class know it
-                * got preempted. Note that none of the switch*_from() methods
-                * know the new class and none of the switch*_to() methods
-                * know the old class.
-                */
-               if (ctx->running && sched_class_above(p->sched_class, ctx->class)) {
-                       rq->next_class->wakeup_preempt(rq, p, 0);
-                       rq->next_class = p->sched_class;
+               if (ctx->running) {
+                       /*
+                        * If this was a class promotion; let the old class
+                        * know it got preempted. Note that none of the
+                        * switch*_from() methods know the new class and none
+                        * of the switch*_to() methods know the old class.
+                        */
+                       if (sched_class_above(p->sched_class, ctx->class)) {
+                               rq->next_class->wakeup_preempt(rq, p, 0);
+                               rq->next_class = p->sched_class;
+                       }
+                       /*
+                        * If this was a degradation in class; make sure to
+                        * reschedule.
+                        */
+                       if (sched_class_above(ctx->class, p->sched_class))
+                               resched_curr(rq);
                }
-
-               /*
-                * If this was a degradation in class someone should have set
-                * need_resched by now.
-                */
-               WARN_ON_ONCE(sched_class_above(ctx->class, p->sched_class) &&
-                            !test_tsk_need_resched(p));
        } else {
                p->sched_class->prio_changed(rq, p, ctx->prio);
        }