Messages in this thread Patch in this message | | | Date | Tue, 5 May 2015 18:08:01 +0200 (CEST) | From | Thomas Gleixner <> | Subject | [PATCH] sched: Handle priority boosted tasks proper in setscheduler() |
| |
Ronny reported that the following scenario is not handled correctly:
T1 (prio = 10) lock(rtmutex);
T2 (prio = 20) lock(rtmutex) boost T1
T1 (prio = 20) sys_set_scheduler(prio = 30) T1 prio = 30 .... sys_set_scheduler(prio = 10) T1 prio = 30
The last step is wrong as T1 should now be back at prio 20.
commit c365c292d0590 "sched: Consider pi boosting in setscheduler()" only handles the case where a boosted tasks tries to lower its priority.
Fix it by taking the new effective priority into account for the decision whether a change of the priority is required.
Reported-by: Ronny Meeus <ronny.meeus@gmail.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- kernel/locking/rtmutex.c | 10 ++++++---- kernel/sched/core.c | 11 +++++------ 2 files changed, 11 insertions(+), 10 deletions(-)
Index: tip/kernel/locking/rtmutex.c =================================================================== --- tip.orig/kernel/locking/rtmutex.c +++ tip/kernel/locking/rtmutex.c @@ -265,15 +265,17 @@ struct task_struct *rt_mutex_get_top_tas } /* - * Called by sched_setscheduler() to check whether the priority change - * is overruled by a possible priority boosting. + * Called by sched_setscheduler() to get the priority which will be + * effective after the change. */ int rt_mutex_check_prio(struct task_struct *task, int newprio) { if (!task_has_pi_waiters(task)) - return 0; + return newprio; - return task_top_pi_waiter(task)->task->prio <= newprio; + if (task_top_pi_waiter(task)->task->prio <= newprio) + return task_top_pi_waiter(task)->task->prio; + return newprio; } /* Index: tip/kernel/sched/core.c =================================================================== --- tip.orig/kernel/sched/core.c +++ tip/kernel/sched/core.c @@ -3414,7 +3414,7 @@ static int __sched_setscheduler(struct t int newprio = dl_policy(attr->sched_policy) ? MAX_DL_PRIO - 1 : MAX_RT_PRIO - 1 - attr->sched_priority; int retval, oldprio, oldpolicy = -1, queued, running; - int policy = attr->sched_policy; + int new_effective_prio, policy = attr->sched_policy; unsigned long flags; const struct sched_class *prev_class; struct rq *rq; @@ -3596,15 +3596,14 @@ change: oldprio = p->prio; /* - * Special case for priority boosted tasks. - * - * If the new priority is lower or equal (user space view) - * than the current (boosted) priority, we just store the new + * Take priority boosted tasks into account. If the new + * effective priority is unchanged, we just store the new * normal parameters and do not touch the scheduler class and * the runqueue. This will be done when the task deboost * itself. */ - if (rt_mutex_check_prio(p, newprio)) { + new_effective_prio = rt_mutex_check_prio(p, newprio); + if (new_effective_prio == oldprio) { __setscheduler_params(p, attr); task_rq_unlock(rq, p, &flags); return 0;
| |