aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-02-17 03:05:48 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-15 12:07:14 -0400
commit371f1d177527b1f815b55a03284ccb2c6dc79c3a (patch)
tree206f58979b6b9df3a4f0caa473c1b4703bb84fd5
parent51c80d13a1d86848e178a5a5ea31cb0edfeb3efe (diff)
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.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index e4b69fae2f33..00a59b090e6f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6065,7 +6065,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
6065 unsigned long flags; 6065 unsigned long flags;
6066 int oldprio, on_rq, running; 6066 int oldprio, on_rq, running;
6067 struct rq *rq; 6067 struct rq *rq;
6068 const struct sched_class *prev_class = p->sched_class; 6068 const struct sched_class *prev_class;
6069 6069
6070 BUG_ON(prio < 0 || prio > MAX_PRIO); 6070 BUG_ON(prio < 0 || prio > MAX_PRIO);
6071 6071
@@ -6073,6 +6073,7 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
6073 update_rq_clock(rq); 6073 update_rq_clock(rq);
6074 6074
6075 oldprio = p->prio; 6075 oldprio = p->prio;
6076 prev_class = p->sched_class;
6076 on_rq = p->se.on_rq; 6077 on_rq = p->se.on_rq;
6077 running = task_current(rq, p); 6078 running = task_current(rq, p);
6078 if (on_rq) 6079 if (on_rq)
@@ -6292,7 +6293,7 @@ static int __sched_setscheduler(struct task_struct *p, int policy,
6292{ 6293{
6293 int retval, oldprio, oldpolicy = -1, on_rq, running; 6294 int retval, oldprio, oldpolicy = -1, on_rq, running;
6294 unsigned long flags; 6295 unsigned long flags;
6295 const struct sched_class *prev_class = p->sched_class; 6296 const struct sched_class *prev_class;
6296 struct rq *rq; 6297 struct rq *rq;
6297 int reset_on_fork; 6298 int reset_on_fork;
6298 6299
@@ -6406,6 +6407,7 @@ recheck:
6406 p->sched_reset_on_fork = reset_on_fork; 6407 p->sched_reset_on_fork = reset_on_fork;
6407 6408
6408 oldprio = p->prio; 6409 oldprio = p->prio;
6410 prev_class = p->sched_class;
6409 __setscheduler(rq, p, policy, param->sched_priority); 6411 __setscheduler(rq, p, policy, param->sched_priority);
6410 6412
6411 if (running) 6413 if (running)