]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] wait_task_inactive should not return on preempt
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 16 Mar 2004 08:38:36 +0000 (00:38 -0800)
committerGreg Kroah-Hartman <greg@kroah.com>
Tue, 16 Mar 2004 08:38:36 +0000 (00:38 -0800)
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.

kernel/sched.c

index 894cb9a406639cdd722255ca29e8d9dd15bcd982..007548c4a883b8b319bbee42196b2fbfaf8a277d 100644 (file)
@@ -594,28 +594,21 @@ void wait_task_inactive(task_t * p)
 {
        unsigned long flags;
        runqueue_t *rq;
+       int preempted;
 
 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);
-       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);
-               preempt_enable();
+               cpu_relax();
+               if (preempted)
+                       yield();
                goto repeat;
        }
        task_rq_unlock(rq, &flags);
-       preempt_enable();
 }
 
 /***