| Subject: sched/rt: Fix wait_task_interactive() to test rt_spin_lock state |
| From: Steven Rostedt <rostedt@goodmis.org> |
| Date: Thu, 01 Mar 2012 13:55:33 -0500 |
| |
| 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> |
| --- |
| kernel/sched/core.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| Index: linux-stable/kernel/sched/core.c |
| =================================================================== |
| --- linux-stable.orig/kernel/sched/core.c |
| +++ linux-stable/kernel/sched/core.c |
| @@ -1172,7 +1172,8 @@ unsigned long wait_task_inactive(struct |
| * 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(); |
| } |
| @@ -1187,7 +1188,8 @@ unsigned long wait_task_inactive(struct |
| 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); |
| |