Skip to content

Commit c365c29

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
sched: Consider pi boosting in setscheduler()
If a PI boosted task policy/priority is modified by a setscheduler() call we unconditionally dequeue and requeue the task if it is on the runqueue even if the new priority is lower than the current effective boosted priority. This can result in undesired reordering of the priority bucket list. If the new priority is less or equal than the current effective we just store the new parameters in the task struct and leave the scheduler class and the runqueue untouched. This is handled when the task deboosts itself. Only if the new priority is higher than the effective boosted priority we apply the change immediately. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> [ Rebase ontop of v3.14-rc1. ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Dario Faggioli <raistlin@linux.it> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1391803122-4425-7-git-send-email-bigeasy@linutronix.de Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 81a44c5 commit c365c29

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

include/linux/sched/rt.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ static inline int rt_task(struct task_struct *p)
1818
#ifdef CONFIG_RT_MUTEXES
1919
extern int rt_mutex_getprio(struct task_struct *p);
2020
extern void rt_mutex_setprio(struct task_struct *p, int prio);
21+
extern int rt_mutex_check_prio(struct task_struct *task, int newprio);
2122
extern struct task_struct *rt_mutex_get_top_task(struct task_struct *task);
2223
extern void rt_mutex_adjust_pi(struct task_struct *p);
2324
static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
@@ -29,6 +30,12 @@ static inline int rt_mutex_getprio(struct task_struct *p)
2930
{
3031
return p->normal_prio;
3132
}
33+
34+
static inline int rt_mutex_check_prio(struct task_struct *task, int newprio)
35+
{
36+
return 0;
37+
}
38+
3239
static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
3340
{
3441
return NULL;

kernel/locking/rtmutex.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,18 @@ struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
212212
return task_top_pi_waiter(task)->task;
213213
}
214214

215+
/*
216+
* Called by sched_setscheduler() to check whether the priority change
217+
* is overruled by a possible priority boosting.
218+
*/
219+
int rt_mutex_check_prio(struct task_struct *task, int newprio)
220+
{
221+
if (!task_has_pi_waiters(task))
222+
return 0;
223+
224+
return task_top_pi_waiter(task)->task->prio <= newprio;
225+
}
226+
215227
/*
216228
* Adjust the priority of a task, after its pi_waiters got modified.
217229
*

kernel/sched/core.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,7 +2902,8 @@ EXPORT_SYMBOL(sleep_on_timeout);
29022902
* This function changes the 'effective' priority of a task. It does
29032903
* not touch ->normal_prio like __setscheduler().
29042904
*
2905-
* Used by the rt_mutex code to implement priority inheritance logic.
2905+
* Used by the rt_mutex code to implement priority inheritance
2906+
* logic. Call site only calls if the priority of the task changed.
29062907
*/
29072908
void rt_mutex_setprio(struct task_struct *p, int prio)
29082909
{
@@ -3171,9 +3172,8 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
31713172
dl_se->dl_new = 1;
31723173
}
31733174

3174-
/* Actually do priority change: must hold pi & rq lock. */
3175-
static void __setscheduler(struct rq *rq, struct task_struct *p,
3176-
const struct sched_attr *attr)
3175+
static void __setscheduler_params(struct task_struct *p,
3176+
const struct sched_attr *attr)
31773177
{
31783178
int policy = attr->sched_policy;
31793179

@@ -3193,18 +3193,21 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
31933193
* getparam()/getattr() don't report silly values for !rt tasks.
31943194
*/
31953195
p->rt_priority = attr->sched_priority;
3196+
set_load_weight(p);
3197+
}
31963198

3197-
p->normal_prio = normal_prio(p);
3198-
p->prio = rt_mutex_getprio(p);
3199+
/* Actually do priority change: must hold pi & rq lock. */
3200+
static void __setscheduler(struct rq *rq, struct task_struct *p,
3201+
const struct sched_attr *attr)
3202+
{
3203+
__setscheduler_params(p, attr);
31993204

32003205
if (dl_prio(p->prio))
32013206
p->sched_class = &dl_sched_class;
32023207
else if (rt_prio(p->prio))
32033208
p->sched_class = &rt_sched_class;
32043209
else
32053210
p->sched_class = &fair_sched_class;
3206-
3207-
set_load_weight(p);
32083211
}
32093212

32103213
static void
@@ -3257,6 +3260,7 @@ static int __sched_setscheduler(struct task_struct *p,
32573260
const struct sched_attr *attr,
32583261
bool user)
32593262
{
3263+
int newprio = MAX_RT_PRIO - 1 - attr->sched_priority;
32603264
int retval, oldprio, oldpolicy = -1, on_rq, running;
32613265
int policy = attr->sched_policy;
32623266
unsigned long flags;
@@ -3427,16 +3431,31 @@ static int __sched_setscheduler(struct task_struct *p,
34273431
return -EBUSY;
34283432
}
34293433

3434+
p->sched_reset_on_fork = reset_on_fork;
3435+
oldprio = p->prio;
3436+
3437+
/*
3438+
* Special case for priority boosted tasks.
3439+
*
3440+
* If the new priority is lower or equal (user space view)
3441+
* than the current (boosted) priority, we just store the new
3442+
* normal parameters and do not touch the scheduler class and
3443+
* the runqueue. This will be done when the task deboost
3444+
* itself.
3445+
*/
3446+
if (rt_mutex_check_prio(p, newprio)) {
3447+
__setscheduler_params(p, attr);
3448+
task_rq_unlock(rq, p, &flags);
3449+
return 0;
3450+
}
3451+
34303452
on_rq = p->on_rq;
34313453
running = task_current(rq, p);
34323454
if (on_rq)
34333455
dequeue_task(rq, p, 0);
34343456
if (running)
34353457
p->sched_class->put_prev_task(rq, p);
34363458

3437-
p->sched_reset_on_fork = reset_on_fork;
3438-
3439-
oldprio = p->prio;
34403459
prev_class = p->sched_class;
34413460
__setscheduler(rq, p, attr);
34423461

0 commit comments

Comments
 (0)