aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/locking/rtmutex.c12
-rw-r--r--kernel/sched/core.c41
2 files changed, 42 insertions, 11 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 2e960a2bab81..aa4dff04b594 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -213,6 +213,18 @@ struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
213} 213}
214 214
215/* 215/*
216 * Called by sched_setscheduler() to check whether the priority change
217 * is overruled by a possible priority boosting.
218 */
219int 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
227/*
216 * Adjust the priority of a task, after its pi_waiters got modified. 228 * Adjust the priority of a task, after its pi_waiters got modified.
217 * 229 *
218 * This can be both boosting and unboosting. task->pi_lock must be held. 230 * This can be both boosting and unboosting. task->pi_lock must be held.
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