]> granicus.if.org Git - spl/commitdiff
Fix subtle race in threads test case
authorBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 28 Jun 2010 19:34:20 +0000 (12:34 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Mon, 28 Jun 2010 19:34:20 +0000 (12:34 -0700)
The call to wake_up() must be moved under the spin lock because
once we drop the lock 'tp' may no longer be valid because the
creating thread has exited.  This basic thread implementation
was correct, this was simply a flaw in the test case.

module/splat/splat-thread.c

index d21ded7959ea59b04a0c08b052f14479d5fb29e5..34810bfffc556a1965a0aed969c135deaa73981f 100644 (file)
@@ -67,9 +67,9 @@ splat_thread_work1(void *priv)
        spin_lock(&tp->tp_lock);
        ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
        tp->tp_rc = 1;
+       wake_up(&tp->tp_waitq);
        spin_unlock(&tp->tp_lock);
 
-       wake_up(&tp->tp_waitq);
        thread_exit();
 }
 
@@ -108,18 +108,17 @@ splat_thread_work2(void *priv)
        spin_lock(&tp->tp_lock);
        ASSERT(tp->tp_magic == SPLAT_THREAD_TEST_MAGIC);
        tp->tp_rc = 1;
+       wake_up(&tp->tp_waitq);
        spin_unlock(&tp->tp_lock);
 
-       wake_up(&tp->tp_waitq);
        thread_exit();
 
        /* The following code is unreachable when thread_exit() is
         * working properly, which is exactly what we're testing */
        spin_lock(&tp->tp_lock);
        tp->tp_rc = 2;
-       spin_unlock(&tp->tp_lock);
-
        wake_up(&tp->tp_waitq);
+       spin_unlock(&tp->tp_lock);
 }
 
 static int