diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2010-02-17 09:05:48 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-15 08:50:17 -0700 |
commit | 04833a6a2dd0f236d1f5c17075a34df9df74351c (patch) | |
tree | 30696936339fcecd60011b8e281da78db19d9e98 | |
parent | 76d071362505e9ea55210b4b5cb7a6824c4c0b22 (diff) | |
download | lwn-04833a6a2dd0f236d1f5c17075a34df9df74351c.tar.gz lwn-04833a6a2dd0f236d1f5c17075a34df9df74351c.zip |
sched: Don't use possibly stale sched_class
commit 83ab0aa0d5623d823444db82c3b3c34d7ec364ae upstream.
setscheduler() saves task->sched_class outside of the rq->lock held
region for a check after the setscheduler changes have become
effective. That might result in checking a stale value.
rtmutex_setprio() has the same problem, though it is protected by
p->pi_lock against setscheduler(), but for correctness sake (and to
avoid bad examples) it needs to be fixed as well.
Retrieve task->sched_class inside of the rq->lock held region.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | kernel/sched.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 4d0109541db1..380e1faecf40 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -6009,7 +6009,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) unsigned long flags; int oldprio, on_rq, running; struct rq *rq; - const struct sched_class *prev_class = p->sched_class; + const struct sched_class *prev_class; BUG_ON(prio < 0 || prio > MAX_PRIO); @@ -6017,6 +6017,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio) update_rq_clock(rq); oldprio = p->prio; + prev_class = p->sched_class; on_rq = p->se.on_rq; running = task_current(rq, p); if (on_rq) @@ -6244,7 +6245,7 @@ static int __sched_setscheduler(struct task_struct *p, int policy, { int retval, oldprio, oldpolicy = -1, on_rq, running; unsigned long flags; - const struct sched_class *prev_class = p->sched_class; + const struct sched_class *prev_class; struct rq *rq; int reset_on_fork; @@ -6358,6 +6359,7 @@ recheck: p->sched_reset_on_fork = reset_on_fork; oldprio = p->prio; + prev_class = p->sched_class; __setscheduler(rq, p, policy, param->sched_priority); if (running) |