Commit 95a2f6d7 authored by Peter Williams's avatar Peter Williams Committed by Linus Torvalds

[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: default avatarPeter Williams <pwil3058@bigpond.net.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent c0799016
......@@ -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 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment