diff options
| author | Dmitry Adamushko <dmitry.adamushko@gmail.com> | 2008-07-01 17:32:15 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-07-18 06:55:14 -0400 |
| commit | 7ebefa8ceefed44cc321be70afc54a585a68ac0b (patch) | |
| tree | cab0118d96d704fcca2e52f192f4bb2a7f6a909e /kernel | |
| parent | 13b40c1e40f3261e83ee514a08b77dbecb93021b (diff) | |
sched: rework of "prioritize non-migratable tasks over migratable ones"
(1) handle in a generic way all cases when a newly woken-up task is
not migratable (not just a corner case when "rt_se->nr_cpus_allowed ==
1")
(2) if current is to be preempted, then make sure "p" will be picked
up by pick_next_task_rt().
i.e. move task's group at the head of its list as well.
currently, it's not a case for the group-scheduling case as described
here: http://www.ussg.iu.edu/hypermail/linux/kernel/0807.0/0134.html
Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Gregory Haskins <ghaskins@novell.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched_rt.c | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 47ceac9e8552..d3d1cccb3d7b 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c | |||
| @@ -599,11 +599,7 @@ static void __enqueue_rt_entity(struct sched_rt_entity *rt_se) | |||
| 599 | if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) | 599 | if (group_rq && (rt_rq_throttled(group_rq) || !group_rq->rt_nr_running)) |
| 600 | return; | 600 | return; |
| 601 | 601 | ||
| 602 | if (rt_se->nr_cpus_allowed == 1) | 602 | list_add_tail(&rt_se->run_list, queue); |
| 603 | list_add(&rt_se->run_list, queue); | ||
| 604 | else | ||
| 605 | list_add_tail(&rt_se->run_list, queue); | ||
| 606 | |||
| 607 | __set_bit(rt_se_prio(rt_se), array->bitmap); | 603 | __set_bit(rt_se_prio(rt_se), array->bitmap); |
| 608 | 604 | ||
| 609 | inc_rt_tasks(rt_se, rt_rq); | 605 | inc_rt_tasks(rt_se, rt_rq); |
| @@ -688,32 +684,34 @@ static void dequeue_task_rt(struct rq *rq, struct task_struct *p, int sleep) | |||
| 688 | * Put task to the end of the run list without the overhead of dequeue | 684 | * Put task to the end of the run list without the overhead of dequeue |
| 689 | * followed by enqueue. | 685 | * followed by enqueue. |
| 690 | */ | 686 | */ |
| 691 | static | 687 | static void |
| 692 | void requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se) | 688 | requeue_rt_entity(struct rt_rq *rt_rq, struct sched_rt_entity *rt_se, int head) |
| 693 | { | 689 | { |
| 694 | struct rt_prio_array *array = &rt_rq->active; | ||
| 695 | |||
| 696 | if (on_rt_rq(rt_se)) { | 690 | if (on_rt_rq(rt_se)) { |
| 697 | list_del_init(&rt_se->run_list); | 691 | struct rt_prio_array *array = &rt_rq->active; |
| 698 | list_add_tail(&rt_se->run_list, | 692 | struct list_head *queue = array->queue + rt_se_prio(rt_se); |
| 699 | array->queue + rt_se_prio(rt_se)); | 693 | |
| 694 | if (head) | ||
| 695 | list_move(&rt_se->run_list, queue); | ||
| 696 | else | ||
| 697 | list_move_tail(&rt_se->run_list, queue); | ||
| 700 | } | 698 | } |
| 701 | } | 699 | } |
| 702 | 700 | ||
| 703 | static void requeue_task_rt(struct rq *rq, struct task_struct *p) | 701 | static void requeue_task_rt(struct rq *rq, struct task_struct *p, int head) |
| 704 | { | 702 | { |
| 705 | struct sched_rt_entity *rt_se = &p->rt; | 703 | struct sched_rt_entity *rt_se = &p->rt; |
| 706 | struct rt_rq *rt_rq; | 704 | struct rt_rq *rt_rq; |
| 707 | 705 | ||
| 708 | for_each_sched_rt_entity(rt_se) { | 706 | for_each_sched_rt_entity(rt_se) { |
| 709 | rt_rq = rt_rq_of_se(rt_se); | 707 | rt_rq = rt_rq_of_se(rt_se); |
| 710 | requeue_rt_entity(rt_rq, rt_se); | 708 | requeue_rt_entity(rt_rq, rt_se, head); |
| 711 | } | 709 | } |
| 712 | } | 710 | } |
| 713 | 711 | ||
| 714 | static void yield_task_rt(struct rq *rq) | 712 | static void yield_task_rt(struct rq *rq) |
| 715 | { | 713 | { |
| 716 | requeue_task_rt(rq, rq->curr); | 714 | requeue_task_rt(rq, rq->curr, 0); |
| 717 | } | 715 | } |
| 718 | 716 | ||
| 719 | #ifdef CONFIG_SMP | 717 | #ifdef CONFIG_SMP |
| @@ -753,6 +751,30 @@ static int select_task_rq_rt(struct task_struct *p, int sync) | |||
| 753 | */ | 751 | */ |
| 754 | return task_cpu(p); | 752 | return task_cpu(p); |
| 755 | } | 753 | } |
| 754 | |||
| 755 | static void check_preempt_equal_prio(struct rq *rq, struct task_struct *p) | ||
| 756 | { | ||
| 757 | cpumask_t mask; | ||
| 758 | |||
| 759 | if (rq->curr->rt.nr_cpus_allowed == 1) | ||
| 760 | return; | ||
| 761 | |||
| 762 | if (p->rt.nr_cpus_allowed != 1 | ||
| 763 | && cpupri_find(&rq->rd->cpupri, p, &mask)) | ||
| 764 | return; | ||
| 765 | |||
| 766 | if (!cpupri_find(&rq->rd->cpupri, rq->curr, &mask)) | ||
| 767 | return; | ||
| 768 | |||
| 769 | /* | ||
| 770 | * There appears to be other cpus that can accept | ||
| 771 | * current and none to run 'p', so lets reschedule | ||
| 772 | * to try and push current away: | ||
| 773 | */ | ||
| 774 | requeue_task_rt(rq, p, 1); | ||
| 775 | resched_task(rq->curr); | ||
| 776 | } | ||
| 777 | |||
| 756 | #endif /* CONFIG_SMP */ | 778 | #endif /* CONFIG_SMP */ |
| 757 | 779 | ||
| 758 | /* | 780 | /* |
| @@ -778,18 +800,8 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p) | |||
| 778 | * to move current somewhere else, making room for our non-migratable | 800 | * to move current somewhere else, making room for our non-migratable |
| 779 | * task. | 801 | * task. |
| 780 | */ | 802 | */ |
| 781 | if((p->prio == rq->curr->prio) | 803 | if (p->prio == rq->curr->prio && !need_resched()) |
| 782 | && p->rt.nr_cpus_allowed == 1 | 804 | check_preempt_equal_prio(rq, p); |
| 783 | && rq->curr->rt.nr_cpus_allowed != 1) { | ||
| 784 | cpumask_t mask; | ||
| 785 | |||
| 786 | if (cpupri_find(&rq->rd->cpupri, rq->curr, &mask)) | ||
| 787 | /* | ||
| 788 | * There appears to be other cpus that can accept | ||
| 789 | * current, so lets reschedule to try and push it away | ||
| 790 | */ | ||
| 791 | resched_task(rq->curr); | ||
| 792 | } | ||
| 793 | #endif | 805 | #endif |
| 794 | } | 806 | } |
| 795 | 807 | ||
| @@ -1415,7 +1427,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p, int queued) | |||
| 1415 | * on the queue: | 1427 | * on the queue: |
| 1416 | */ | 1428 | */ |
| 1417 | if (p->rt.run_list.prev != p->rt.run_list.next) { | 1429 | if (p->rt.run_list.prev != p->rt.run_list.next) { |
| 1418 | requeue_task_rt(rq, p); | 1430 | requeue_task_rt(rq, p, 0); |
| 1419 | set_tsk_need_resched(p); | 1431 | set_tsk_need_resched(p); |
| 1420 | } | 1432 | } |
| 1421 | } | 1433 | } |
