aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched/core.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2014-02-07 14:58:42 -0500
committerIngo Molnar <mingo@kernel.org>2014-02-22 12:10:04 -0500
commitc365c292d05908c6ea6f32708f331e21033fe71d (patch)
treefcaf27f6d0296ef48203f940d1ed9d8c02c56860 /kernel/sched/core.c
parent81a44c5441d7f7d2c3dc9105f4d65ad0d5818617 (diff)
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>
Diffstat (limited to 'kernel/sched/core.c')
-rw-r--r--kernel/sched/core.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 9c2fcbf9a266..003263b3b05c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2902,7 +2902,8 @@ EXPORT_SYMBOL(sleep_on_timeout);
2902 * This function changes the 'effective' priority of a task. It does 2902 * This function changes the 'effective' priority of a task. It does
2903 * not touch ->normal_prio like __setscheduler(). 2903 * not touch ->normal_prio like __setscheduler().
2904 * 2904 *
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.
2906 */ 2907 */
2907void rt_mutex_setprio(struct task_struct *p, int prio) 2908void rt_mutex_setprio(struct task_struct *p, int prio)
2908{ 2909{
@@ -3171,9 +3172,8 @@ __setparam_dl(struct task_struct *p, const struct sched_attr *attr)
3171 dl_se->dl_new = 1; 3172 dl_se->dl_new = 1;
3172} 3173}
3173 3174
3174/* Actually do priority change: must hold pi & rq lock. */ 3175static void __setscheduler_params(struct task_struct *p,
3175static void __setscheduler(struct rq *rq, struct task_struct *p, 3176 const struct sched_attr *attr)
3176 const struct sched_attr *attr)
3177{ 3177{
3178 int policy = attr->sched_policy; 3178 int policy = attr->sched_policy;
3179 3179
@@ -3193,9 +3193,14 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
3193 * getparam()/getattr() don't report silly values for !rt tasks. 3193 * getparam()/getattr() don't report silly values for !rt tasks.
3194 */ 3194 */
3195 p->rt_priority = attr->sched_priority; 3195 p->rt_priority = attr->sched_priority;
3196 set_load_weight(p);
3197}
3196 3198
3197 p->normal_prio = normal_prio(p); 3199/* Actually do priority change: must hold pi & rq lock. */
3198 p->prio = rt_mutex_getprio(p); 3200static void __setscheduler(struct rq *rq, struct task_struct *p,
3201 const struct sched_attr *attr)
3202{
3203 __setscheduler_params(p, attr);
3199 3204
3200 if (dl_prio(p->prio)) 3205 if (dl_prio(p->prio))
3201 p->sched_class = &dl_sched_class; 3206 p->sched_class = &dl_sched_class;
@@ -3203,8 +3208,6 @@ static void __setscheduler(struct rq *rq, struct task_struct *p,
3203 p->sched_class = &rt_sched_class; 3208 p->sched_class = &rt_sched_class;
3204 else 3209 else
3205 p->sched_class = &fair_sched_class; 3210 p->sched_class = &fair_sched_class;
3206
3207 set_load_weight(p);
3208} 3211}
3209 3212
3210static void 3213static void
@@ -3257,6 +3260,7 @@ static int __sched_setscheduler(struct task_struct *p,
3257 const struct sched_attr *attr, 3260 const struct sched_attr *attr,
3258 bool user) 3261 bool user)
3259{ 3262{
3263 int newprio = MAX_RT_PRIO - 1 - attr->sched_priority;
3260 int retval, oldprio, oldpolicy = -1, on_rq, running; 3264 int retval, oldprio, oldpolicy = -1, on_rq, running;
3261 int policy = attr->sched_policy; 3265 int policy = attr->sched_policy;
3262 unsigned long flags; 3266 unsigned long flags;
@@ -3427,6 +3431,24 @@ change:
3427 return -EBUSY; 3431 return -EBUSY;
3428 } 3432 }
3429 3433
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
3430 on_rq = p->on_rq; 3452 on_rq = p->on_rq;
3431 running = task_current(rq, p); 3453 running = task_current(rq, p);
3432 if (on_rq) 3454 if (on_rq)
@@ -3434,9 +3456,6 @@ change:
3434 if (running) 3456 if (running)
3435 p->sched_class->put_prev_task(rq, p); 3457 p->sched_class->put_prev_task(rq, p);
3436 3458
3437 p->sched_reset_on_fork = reset_on_fork;
3438
3439 oldprio = p->prio;
3440 prev_class = p->sched_class; 3459 prev_class = p->sched_class;
3441 __setscheduler(rq, p, attr); 3460 __setscheduler(rq, p, attr);
3442 3461