summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorPeter Williams <pwil3058@bigpond.net.au>2004-10-18 09:11:14 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-10-18 09:11:14 -0700
commit95a2f6d75d878126b883e87a5fd028e971851c93 (patch)
tree5999b66ddce8d403ceaa26b97a9f0e80f2b01364 /kernel
parentc07990160b13946faf43d716a8902f6f7cf55a5e (diff)
[PATCH] CPU Scheduler: fix potential error in runqueue nr_uninterruptible count
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>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 2e67de4b356a..3b498fa4f3d7 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -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.