Since the change in commit fd7a4bed1835 ("sched, rt: Convert
switched_{from, to}_rt() / prio_changed_rt() to balance callbacks") we
don't reschedule a task under certain circumstances:

Lets say taskA, SCHED_OTHER, is running on CPU0 (and it may run only on
CPU0) and holds a PI lock. This task is removed from the CPU because it
used up its time slice and another SCHED_OTHER task is running. TaskB on
CPU1 runs at RT priority and asks for the lock owned by taskA. This
results in a priority boost for taskA. TaskB goes to sleep until the
lock has been made available. TaskA is already runable (but not active)
so it receives no wake up.
The reality now is that taskA gets on the CPU once the scheduler decides
to remove the current task despite the fact that a high priority task is
enqueued and waiting. This may take a long time.
The desired behaviour is that CPU0 immediately reschedules after the
priority boost which made taskA the task with the lowest priority.

Fixes: fd7a4bed1835 ("sched, rt: Convert switched_{from, to}_rt() /
                     prio_changed_rt() to balance callbacks")
Suggested-by: Peter Zijlstra <[email protected]>
Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
---
 kernel/sched/rt.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 88254be118b0..cdba8d58dbc5 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -2198,10 +2198,10 @@ static void switched_to_rt(struct rq *rq, struct 
task_struct *p)
 #ifdef CONFIG_SMP
                if (tsk_nr_cpus_allowed(p) > 1 && rq->rt.overloaded)
                        queue_push_tasks(rq);
-#else
+               else
+#endif /* CONFIG_SMP */
                if (p->prio < rq->curr->prio)
                        resched_curr(rq);
-#endif /* CONFIG_SMP */
        }
 }
 
-- 
2.11.0

Reply via email to