From: pwil3058@bigpond.net.au Problem: In the function try_to_wake_up(), when the runqueue's nr_uninterruptible field is decremented it's possible (on SMP systems) that the pointer no longer points to the runqueue that the task being woken was on when it went to sleep. This would cause the wrong runqueue's field to be decremented and the correct one tp remain unchanged. Fix: Save a pointer to the old runqueue at the beginning of the function and use it when decrementing nr_uninterruptible. Signed-off-by: Peter Williams Signed-off-by: Andrew Morton --- 25-akpm/kernel/sched.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff -puN kernel/sched.c~cpu-scheduler-fix-potential-error-in-runqueue-nr_uninterruptible-count kernel/sched.c --- 25/kernel/sched.c~cpu-scheduler-fix-potential-error-in-runqueue-nr_uninterruptible-count 2004-10-01 11:34:24.548700976 -0700 +++ 25-akpm/kernel/sched.c 2004-10-01 11:34:24.554700064 -0700 @@ -981,14 +981,14 @@ static int try_to_wake_up(task_t * p, un int cpu, this_cpu, success = 0; unsigned long flags; long old_state; - runqueue_t *rq; + runqueue_t *rq, *old_rq; #ifdef CONFIG_SMP unsigned long load, this_load; struct sched_domain *sd; int new_cpu; #endif - rq = task_rq_lock(p, &flags); + old_rq = rq = task_rq_lock(p, &flags); schedstat_inc(rq, ttwu_cnt); old_state = p->state; if (!(old_state & state)) @@ -1083,7 +1083,7 @@ out_set_cpu: out_activate: #endif /* CONFIG_SMP */ if (old_state == TASK_UNINTERRUPTIBLE) { - rq->nr_uninterruptible--; + old_rq->nr_uninterruptible--; /* * Tasks on involuntary sleep don't earn * sleep_avg beyond just interactive state. _