diff options
Diffstat (limited to 'kernel/sched/deadline.c')
-rw-r--r-- | kernel/sched/deadline.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 256e577faf1b..5285332392d5 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c | |||
@@ -518,12 +518,20 @@ again: | |||
518 | } | 518 | } |
519 | 519 | ||
520 | /* | 520 | /* |
521 | * We need to take care of a possible races here. In fact, the | 521 | * We need to take care of several possible races here: |
522 | * task might have changed its scheduling policy to something | 522 | * |
523 | * different from SCHED_DEADLINE or changed its reservation | 523 | * - the task might have changed its scheduling policy |
524 | * parameters (through sched_setattr()). | 524 | * to something different than SCHED_DEADLINE |
525 | * - the task might have changed its reservation parameters | ||
526 | * (through sched_setattr()) | ||
527 | * - the task might have been boosted by someone else and | ||
528 | * might be in the boosting/deboosting path | ||
529 | * | ||
530 | * In all this cases we bail out, as the task is already | ||
531 | * in the runqueue or is going to be enqueued back anyway. | ||
525 | */ | 532 | */ |
526 | if (!dl_task(p) || dl_se->dl_new) | 533 | if (!dl_task(p) || dl_se->dl_new || |
534 | dl_se->dl_boosted || !dl_se->dl_throttled) | ||
527 | goto unlock; | 535 | goto unlock; |
528 | 536 | ||
529 | sched_clock_tick(); | 537 | sched_clock_tick(); |
@@ -532,7 +540,7 @@ again: | |||
532 | dl_se->dl_yielded = 0; | 540 | dl_se->dl_yielded = 0; |
533 | if (task_on_rq_queued(p)) { | 541 | if (task_on_rq_queued(p)) { |
534 | enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); | 542 | enqueue_task_dl(rq, p, ENQUEUE_REPLENISH); |
535 | if (task_has_dl_policy(rq->curr)) | 543 | if (dl_task(rq->curr)) |
536 | check_preempt_curr_dl(rq, p, 0); | 544 | check_preempt_curr_dl(rq, p, 0); |
537 | else | 545 | else |
538 | resched_curr(rq); | 546 | resched_curr(rq); |
@@ -847,8 +855,19 @@ static void enqueue_task_dl(struct rq *rq, struct task_struct *p, int flags) | |||
847 | * smaller than our one... OTW we keep our runtime and | 855 | * smaller than our one... OTW we keep our runtime and |
848 | * deadline. | 856 | * deadline. |
849 | */ | 857 | */ |
850 | if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio)) | 858 | if (pi_task && p->dl.dl_boosted && dl_prio(pi_task->normal_prio)) { |
851 | pi_se = &pi_task->dl; | 859 | pi_se = &pi_task->dl; |
860 | } else if (!dl_prio(p->normal_prio)) { | ||
861 | /* | ||
862 | * Special case in which we have a !SCHED_DEADLINE task | ||
863 | * that is going to be deboosted, but exceedes its | ||
864 | * runtime while doing so. No point in replenishing | ||
865 | * it, as it's going to return back to its original | ||
866 | * scheduling class after this. | ||
867 | */ | ||
868 | BUG_ON(!p->dl.dl_boosted || flags != ENQUEUE_REPLENISH); | ||
869 | return; | ||
870 | } | ||
852 | 871 | ||
853 | /* | 872 | /* |
854 | * If p is throttled, we do nothing. In fact, if it exhausted | 873 | * If p is throttled, we do nothing. In fact, if it exhausted |
@@ -1607,8 +1626,12 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p) | |||
1607 | /* Only reschedule if pushing failed */ | 1626 | /* Only reschedule if pushing failed */ |
1608 | check_resched = 0; | 1627 | check_resched = 0; |
1609 | #endif /* CONFIG_SMP */ | 1628 | #endif /* CONFIG_SMP */ |
1610 | if (check_resched && task_has_dl_policy(rq->curr)) | 1629 | if (check_resched) { |
1611 | check_preempt_curr_dl(rq, p, 0); | 1630 | if (dl_task(rq->curr)) |
1631 | check_preempt_curr_dl(rq, p, 0); | ||
1632 | else | ||
1633 | resched_curr(rq); | ||
1634 | } | ||
1612 | } | 1635 | } |
1613 | } | 1636 | } |
1614 | 1637 | ||