This patch doesn't apply to the .36 stable tree If someone wants it applied there, please email the backport to [email protected]
thanks, greg k-h > commit: f26f9aff6aaf67e9a430d16c266f91b13a5bff64 > From: Mike Galbraith <[email protected]> > Date: Wed, 8 Dec 2010 11:05:42 +0100 > Subject: [PATCH] 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 unconditionally in schedule() proper instead of conditionally > in put_prev_task(). > > Signed-off-by: Mike Galbraith <[email protected]> > Reported-by: Bjoern B. Brandenburg <[email protected]> > Tested-by: Yong Zhang <[email protected]> > Signed-off-by: Peter Zijlstra <[email protected]> > Cc: [email protected] > LKML-Reference: <[email protected]> > Signed-off-by: Ingo Molnar <[email protected]> > --- > kernel/fork.c | 1 + > kernel/sched.c | 26 ++++++++++++++------------ > 2 files changed, 15 insertions(+), 12 deletions(-) > > diff --git a/kernel/fork.c b/kernel/fork.c > index 3b159c5..5447dc7 100644 > --- a/kernel/fork.c > +++ b/kernel/fork.c > @@ -273,6 +273,7 @@ static struct task_struct *dup_task_struct(struct > task_struct *orig) > > setup_thread_stack(tsk, orig); > clear_user_return_notifier(tsk); > + clear_tsk_need_resched(tsk); > stackend = end_of_stack(tsk); > *stackend = STACK_END_MAGIC; /* for overflow detection */ > > diff --git a/kernel/sched.c b/kernel/sched.c > index 6b7c26a..da14302 100644 > --- a/kernel/sched.c > +++ b/kernel/sched.c > @@ -641,17 +641,18 @@ static void sched_irq_time_avg_update(struct rq *rq, > u64 irq_time); > > inline void update_rq_clock(struct rq *rq) > { > - if (!rq->skip_clock_update) { > - int cpu = cpu_of(rq); > - u64 irq_time; > + int cpu = cpu_of(rq); > + u64 irq_time; > > - rq->clock = sched_clock_cpu(cpu); > - irq_time = irq_time_cpu(cpu); > - if (rq->clock - irq_time > rq->clock_task) > - rq->clock_task = rq->clock - irq_time; > + if (rq->skip_clock_update) > + return; > > - sched_irq_time_avg_update(rq, irq_time); > - } > + rq->clock = sched_clock_cpu(cpu); > + irq_time = irq_time_cpu(cpu); > + if (rq->clock - irq_time > rq->clock_task) > + rq->clock_task = rq->clock - irq_time; > + > + sched_irq_time_avg_update(rq, irq_time); > } > > /* > @@ -2129,7 +2130,7 @@ static void check_preempt_curr(struct rq *rq, struct > task_struct *p, int flags) > * A queue event has occurred, and we're going to schedule. In > * this case, we can save a useless back to back clock update. > */ > - if (test_tsk_need_resched(rq->curr)) > + if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr)) > rq->skip_clock_update = 1; > } > > @@ -3973,7 +3974,6 @@ static void put_prev_task(struct rq *rq, struct > task_struct *prev) > { > if (prev->se.on_rq) > update_rq_clock(rq); > - rq->skip_clock_update = 0; > prev->sched_class->put_prev_task(rq, prev); > } > > @@ -4031,7 +4031,6 @@ need_resched_nonpreemptible: > hrtick_clear(rq); > > raw_spin_lock_irq(&rq->lock); > - clear_tsk_need_resched(prev); > > switch_count = &prev->nivcsw; > if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { > @@ -4063,6 +4062,8 @@ need_resched_nonpreemptible: > > put_prev_task(rq, prev); > next = pick_next_task(rq); > + clear_tsk_need_resched(prev); > + rq->skip_clock_update = 0; > > if (likely(prev != next)) { > sched_info_switch(prev, next); > @@ -4071,6 +4072,7 @@ need_resched_nonpreemptible: > rq->nr_switches++; > rq->curr = next; > ++*switch_count; > + WARN_ON_ONCE(test_tsk_need_resched(next)); > > context_switch(rq, prev, next); /* unlocks the rq */ > /* > > _______________________________________________ > stable mailing list > [email protected] > http://linux.kernel.org/mailman/listinfo/stable _______________________________________________ stable mailing list [email protected] http://linux.kernel.org/mailman/listinfo/stable
