aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorMike Galbraith <efault@gmx.de>2010-12-06 00:33:27 -0500
committerBjoern B. Brandenburg <bbb@cs.unc.edu>2010-12-06 09:26:59 -0500
commitee0e01a2e4d3b9266ca44a83271b22aa59b289f3 (patch)
tree0c1789f277863a1345580123e65a46e2869c6089 /kernel/sched.c
parent771f8bc71c31c6bd103cdec283012253f352ab1c (diff)
Scheduler bug related to rq->skip_clock_update?
On Sun, 2010-12-05 at 13:28 +0800, Yong Zhang wrote: > when we init idle task, we doesn't mark it on_rq. > My test show the concern is smoothed by below patch. Close :) The skip_clock_update flag should only be set if rq->curr is on_rq, because it it _that_ clock update during dequeue, and subsequent microscopic vruntime update it causes that we're trying to avoid. I think the below fixes it up properly. Sched: fix skip_clock_update optimization idle_balance() drops/retakes rq->lock, leaving the previous task vulnerable to set_tsk_need_resched(). Clear it after we return from balancing instead, and in setup_thread_stack() as well, so no successfully descheduled or never scheduled task has it set. Need resched confused the skip_clock_update logic, which assumes that the next call to update_rq_clock() will come nearly immediately after being set. Make the optimization robust against the waking a sleeper before it sucessfully deschedules case by checking that the current task has not been dequeued before setting the flag, since it is that useless clock update we're trying to save, and clear in update_rq_clock() to ensure that ONE call may be skipped. Signed-off-by: Mike Galbraith <efault@gmx.de> Cc: Ingo Molnar <mingo@elte.hu> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Bjoern B. Brandenburg <bbb.lst@gmail.com> Reported-by: Bjoern B. Brandenburg <bbb.lst@gmail.com>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index dc91a4d09ac3..651c899a9b74 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -652,6 +652,7 @@ inline void update_rq_clock(struct rq *rq)
652 652
653 sched_irq_time_avg_update(rq, irq_time); 653 sched_irq_time_avg_update(rq, irq_time);
654 } 654 }
655 rq->skip_clock_update = 0;
655} 656}
656 657
657/* 658/*
@@ -2129,7 +2130,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
2129 * A queue event has occurred, and we're going to schedule. In 2130 * A queue event has occurred, and we're going to schedule. In
2130 * this case, we can save a useless back to back clock update. 2131 * this case, we can save a useless back to back clock update.
2131 */ 2132 */
2132 if (test_tsk_need_resched(rq->curr)) 2133 if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))
2133 rq->skip_clock_update = 1; 2134 rq->skip_clock_update = 1;
2134} 2135}
2135 2136
@@ -3845,7 +3846,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)
3845{ 3846{
3846 if (prev->se.on_rq) 3847 if (prev->se.on_rq)
3847 update_rq_clock(rq); 3848 update_rq_clock(rq);
3848 rq->skip_clock_update = 0;
3849 prev->sched_class->put_prev_task(rq, prev); 3849 prev->sched_class->put_prev_task(rq, prev);
3850} 3850}
3851 3851
@@ -3903,7 +3903,6 @@ need_resched_nonpreemptible:
3903 hrtick_clear(rq); 3903 hrtick_clear(rq);
3904 3904
3905 raw_spin_lock_irq(&rq->lock); 3905 raw_spin_lock_irq(&rq->lock);
3906 clear_tsk_need_resched(prev);
3907 3906
3908 switch_count = &prev->nivcsw; 3907 switch_count = &prev->nivcsw;
3909 if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { 3908 if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
@@ -3933,6 +3932,7 @@ need_resched_nonpreemptible:
3933 if (unlikely(!rq->nr_running)) 3932 if (unlikely(!rq->nr_running))
3934 idle_balance(cpu, rq); 3933 idle_balance(cpu, rq);
3935 3934
3935 clear_tsk_need_resched(prev);
3936 put_prev_task(rq, prev); 3936 put_prev_task(rq, prev);
3937 next = pick_next_task(rq); 3937 next = pick_next_task(rq);
3938 3938