]> git.hungrycats.org Git - linux/commitdiff
[PATCH] CPU Scheduler: fix potential error in runqueue nr_uninterruptible count
authorPeter Williams <pwil3058@bigpond.net.au>
Mon, 18 Oct 2004 16:11:14 +0000 (09:11 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 18 Oct 2004 16:11:14 +0000 (09:11 -0700)
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 <pwil3058@bigpond.net.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
kernel/sched.c

index 2e67de4b356a63f5a8c7778628ec72f79ecfd50b..3b498fa4f3d75b54d6e77f4bded611fb9972a087 100644 (file)
@@ -981,14 +981,14 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
        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.