diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 54 |
1 files changed, 46 insertions, 8 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 7c9098d186e6..168b2680ae27 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -2614,9 +2614,32 @@ void sched_fork(struct task_struct *p, int clone_flags) | |||
2614 | set_task_cpu(p, cpu); | 2614 | set_task_cpu(p, cpu); |
2615 | 2615 | ||
2616 | /* | 2616 | /* |
2617 | * Make sure we do not leak PI boosting priority to the child: | 2617 | * Make sure we do not leak PI boosting priority to the child. |
2618 | */ | 2618 | */ |
2619 | p->prio = current->normal_prio; | 2619 | p->prio = current->normal_prio; |
2620 | |||
2621 | /* | ||
2622 | * Revert to default priority/policy on fork if requested. | ||
2623 | */ | ||
2624 | if (unlikely(p->sched_reset_on_fork)) { | ||
2625 | if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) | ||
2626 | p->policy = SCHED_NORMAL; | ||
2627 | |||
2628 | if (p->normal_prio < DEFAULT_PRIO) | ||
2629 | p->prio = DEFAULT_PRIO; | ||
2630 | |||
2631 | if (PRIO_TO_NICE(p->static_prio) < 0) { | ||
2632 | p->static_prio = NICE_TO_PRIO(0); | ||
2633 | set_load_weight(p); | ||
2634 | } | ||
2635 | |||
2636 | /* | ||
2637 | * We don't need the reset flag anymore after the fork. It has | ||
2638 | * fulfilled its duty: | ||
2639 | */ | ||
2640 | p->sched_reset_on_fork = 0; | ||
2641 | } | ||
2642 | |||
2620 | if (!rt_prio(p->prio)) | 2643 | if (!rt_prio(p->prio)) |
2621 | p->sched_class = &fair_sched_class; | 2644 | p->sched_class = &fair_sched_class; |
2622 | 2645 | ||
@@ -6100,17 +6123,25 @@ static int __sched_setscheduler(struct task_struct *p, int policy, | |||
6100 | unsigned long flags; | 6123 | unsigned long flags; |
6101 | const struct sched_class *prev_class = p->sched_class; | 6124 | const struct sched_class *prev_class = p->sched_class; |
6102 | struct rq *rq; | 6125 | struct rq *rq; |
6126 | int reset_on_fork; | ||
6103 | 6127 | ||
6104 | /* may grab non-irq protected spin_locks */ | 6128 | /* may grab non-irq protected spin_locks */ |
6105 | BUG_ON(in_interrupt()); | 6129 | BUG_ON(in_interrupt()); |
6106 | recheck: | 6130 | recheck: |
6107 | /* double check policy once rq lock held */ | 6131 | /* double check policy once rq lock held */ |
6108 | if (policy < 0) | 6132 | if (policy < 0) { |
6133 | reset_on_fork = p->sched_reset_on_fork; | ||
6109 | policy = oldpolicy = p->policy; | 6134 | policy = oldpolicy = p->policy; |
6110 | else if (policy != SCHED_FIFO && policy != SCHED_RR && | 6135 | } else { |
6111 | policy != SCHED_NORMAL && policy != SCHED_BATCH && | 6136 | reset_on_fork = !!(policy & SCHED_RESET_ON_FORK); |
6112 | policy != SCHED_IDLE) | 6137 | policy &= ~SCHED_RESET_ON_FORK; |
6113 | return -EINVAL; | 6138 | |
6139 | if (policy != SCHED_FIFO && policy != SCHED_RR && | ||
6140 | policy != SCHED_NORMAL && policy != SCHED_BATCH && | ||
6141 | policy != SCHED_IDLE) | ||
6142 | return -EINVAL; | ||
6143 | } | ||
6144 | |||
6114 | /* | 6145 | /* |
6115 | * Valid priorities for SCHED_FIFO and SCHED_RR are | 6146 | * Valid priorities for SCHED_FIFO and SCHED_RR are |
6116 | * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL, | 6147 | * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL, |
@@ -6154,6 +6185,10 @@ recheck: | |||
6154 | /* can't change other user's priorities */ | 6185 | /* can't change other user's priorities */ |
6155 | if (!check_same_owner(p)) | 6186 | if (!check_same_owner(p)) |
6156 | return -EPERM; | 6187 | return -EPERM; |
6188 | |||
6189 | /* Normal users shall not reset the sched_reset_on_fork flag */ | ||
6190 | if (p->sched_reset_on_fork && !reset_on_fork) | ||
6191 | return -EPERM; | ||
6157 | } | 6192 | } |
6158 | 6193 | ||
6159 | if (user) { | 6194 | if (user) { |
@@ -6197,6 +6232,8 @@ recheck: | |||
6197 | if (running) | 6232 | if (running) |
6198 | p->sched_class->put_prev_task(rq, p); | 6233 | p->sched_class->put_prev_task(rq, p); |
6199 | 6234 | ||
6235 | p->sched_reset_on_fork = reset_on_fork; | ||
6236 | |||
6200 | oldprio = p->prio; | 6237 | oldprio = p->prio; |
6201 | __setscheduler(rq, p, policy, param->sched_priority); | 6238 | __setscheduler(rq, p, policy, param->sched_priority); |
6202 | 6239 | ||
@@ -6313,14 +6350,15 @@ SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) | |||
6313 | if (p) { | 6350 | if (p) { |
6314 | retval = security_task_getscheduler(p); | 6351 | retval = security_task_getscheduler(p); |
6315 | if (!retval) | 6352 | if (!retval) |
6316 | retval = p->policy; | 6353 | retval = p->policy |
6354 | | (p->sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0); | ||
6317 | } | 6355 | } |
6318 | read_unlock(&tasklist_lock); | 6356 | read_unlock(&tasklist_lock); |
6319 | return retval; | 6357 | return retval; |
6320 | } | 6358 | } |
6321 | 6359 | ||
6322 | /** | 6360 | /** |
6323 | * sys_sched_getscheduler - get the RT priority of a thread | 6361 | * sys_sched_getparam - get the RT priority of a thread |
6324 | * @pid: the pid in question. | 6362 | * @pid: the pid in question. |
6325 | * @param: structure containing the RT priority. | 6363 | * @param: structure containing the RT priority. |
6326 | */ | 6364 | */ |