sched: Don't use possibly stale sched_class
authorThomas Gleixner <tglx@linutronix.de>
Wed, 17 Feb 2010 08:05:48 +0000 (09:05 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 17 Feb 2010 10:58:18 +0000 (11:58 +0100)
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>
Cc: stable@kernel.org
kernel/sched.c

index af5fa23..0b914fc 100644 (file)
@@ -4249,7 +4249,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);
 
@@ -4257,6 +4257,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)
@@ -4476,7 +4477,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;
 
@@ -4590,6 +4591,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)