diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/locking/rtmutex.c | 12 | ||||
-rw-r--r-- | kernel/sched/core.c | 41 |
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 | */ | ||
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 | |||
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 | */ |
2907 | void rt_mutex_setprio(struct task_struct *p, int prio) | 2908 | void 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. */ | 3175 | static void __setscheduler_params(struct task_struct *p, |
3175 | static 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); | 3200 | static 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 | ||
3210 | static void | 3213 | static 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 | ||