diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2012-03-01 18:55:33 (GMT) |
---|---|---|
committer | Scott Wood <scottwood@freescale.com> | 2013-04-04 22:09:34 (GMT) |
commit | 5673cd604eeee718e563f6a551a82e7cb48df7d5 (patch) | |
tree | 03a36b97ec803b508bef14966ea0b81fac44f3b1 /kernel | |
parent | ce9c0cba2799ec2657231ae7b5e86f154b9d2a73 (diff) | |
download | linux-fsl-qoriq-5673cd604eeee718e563f6a551a82e7cb48df7d5.tar.xz |
sched/rt: Fix wait_task_interactive() to test rt_spin_lock state
The wait_task_interactive() will have a task sleep waiting for another
task to have a certain state. But it ignores the rt_spin_locks state
and can return with an incorrect result if the task it is waiting
for is blocked on a rt_spin_lock() and is waking up.
The rt_spin_locks save the tasks state in the saved_state field
and the wait_task_interactive() must also test that state.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Carsten Emde <C.Emde@osadl.org>
Cc: John Kacur <jkacur@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Clark Williams <clark.williams@gmail.com>
Cc: stable-rt@vger.kernel.org
Link: http://lkml.kernel.org/r/20120301190345.979435764@goodmis.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched/core.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 7d852af..c11a9cc 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1041,7 +1041,8 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) * is actually now running somewhere else! */ while (task_running(rq, p)) { - if (match_state && unlikely(p->state != match_state)) + if (match_state && unlikely(p->state != match_state) + && unlikely(p->saved_state != match_state)) return 0; cpu_relax(); } @@ -1056,7 +1057,8 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state) running = task_running(rq, p); on_rq = p->on_rq; ncsw = 0; - if (!match_state || p->state == match_state) + if (!match_state || p->state == match_state + || p->saved_state == match_state) ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ task_rq_unlock(rq, p, &flags); |