Commit 3da04c35 authored by Rusty Russell's avatar Rusty Russell Committed by Greg Kroah-Hartman

[PATCH] wait_task_inactive should not return on preempt

wait_task_inactive is now only used in two non-time-critical places: the
ptrace code to guarantee a schedule and kthread_bind so we can change
the thread CPU.  Unfortunately with preempt, the code as stands has a
race: we might return because the thread is preempted, not because it
actually reached schedule().  The ptrace code (probably) doesn't care,
but the kthread code does.

This patch simplifies the (now over-optimized) code, and does a yield()
for the preemption case.
parent a137983b
...@@ -594,28 +594,21 @@ void wait_task_inactive(task_t * p) ...@@ -594,28 +594,21 @@ void wait_task_inactive(task_t * p)
{ {
unsigned long flags; unsigned long flags;
runqueue_t *rq; runqueue_t *rq;
int preempted;
repeat: repeat:
preempt_disable();
rq = task_rq(p);
if (unlikely(task_running(rq, p))) {
cpu_relax();
/*
* enable/disable preemption just to make this
* a preemption point - we are busy-waiting
* anyway.
*/
preempt_enable();
goto repeat;
}
rq = task_rq_lock(p, &flags); rq = task_rq_lock(p, &flags);
if (unlikely(task_running(rq, p))) { /* Must be off runqueue entirely, not preempted. */
if (unlikely(p->array)) {
/* If it's preempted, we yield. It could be a while. */
preempted = !task_running(rq, p);
task_rq_unlock(rq, &flags); task_rq_unlock(rq, &flags);
preempt_enable(); cpu_relax();
if (preempted)
yield();
goto repeat; goto repeat;
} }
task_rq_unlock(rq, &flags); task_rq_unlock(rq, &flags);
preempt_enable();
} }
/*** /***
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment