Index: /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25647)
+++ /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25648)
@@ -1233,4 +1233,5 @@
     rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
     ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
+    pThreadSelf->LockValidator.enmRecState = enmSleepState;
     rtThreadSetState(pThreadSelf, enmSleepState);
 
@@ -1260,5 +1261,8 @@
         ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping);
     else
+    {
         rtThreadSetState(pThreadSelf, enmThreadState);
+        rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL);
+    }
     ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false);
     return rc;
@@ -1434,4 +1438,5 @@
     rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
     ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
+    pThreadSelf->LockValidator.enmRecState = enmSleepState;
     rtThreadSetState(pThreadSelf, enmSleepState);
 
@@ -1461,5 +1466,8 @@
         ASMAtomicWriteBool(&pThreadSelf->fReallySleeping, fReallySleeping);
     else
+    {
         rtThreadSetState(pThreadSelf, enmThreadState);
+        rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, NULL);
+    }
     ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, false);
     return rc;
Index: /trunk/src/VBox/Runtime/common/misc/thread.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/thread.cpp	(revision 25647)
+++ /trunk/src/VBox/Runtime/common/misc/thread.cpp	(revision 25648)
@@ -1334,6 +1334,20 @@
         Assert(pThread == RTThreadSelf());
         ASMAtomicWriteBool(&pThread->fReallySleeping, false);
-        if (rtThreadGetState(pThread) == enmCurState)
+
+        RTTHREADSTATE enmActualState = rtThreadGetState(pThread);
+        if (enmActualState == enmCurState)
+        {
             rtThreadSetState(pThread, RTTHREADSTATE_RUNNING);
+            if (   pThread->LockValidator.pRec
+                && pThread->LockValidator.enmRecState == enmCurState)
+                ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
+        }
+        /* This is a bit ugly... :-/ */
+        else if (   (   enmActualState == RTTHREADSTATE_TERMINATED
+                     || enmActualState == RTTHREADSTATE_INITIALIZING)
+                 && pThread->LockValidator.pRec)
+            ASMAtomicWritePtr((void * volatile *)&pThread->LockValidator.pRec, NULL);
+        Assert(   pThread->LockValidator.pRec == NULL
+               || RTTHREAD_IS_SLEEPING(enmActualState));
     }
 }
Index: /trunk/src/VBox/Runtime/include/internal/lockvalidator.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/lockvalidator.h	(revision 25647)
+++ /trunk/src/VBox/Runtime/include/internal/lockvalidator.h	(revision 25648)
@@ -59,16 +59,22 @@
     /** Where we are blocking. */
     RTLOCKVALSRCPOS                 SrcPos;
-    /** What we're blocking on. */
+    /** What we're blocking on.
+     * The lock validator sets this, RTThreadUnblock clears it. */
     PRTLOCKVALRECUNION volatile     pRec;
+    /** The state in which pRec that goes with pRec.
+     * RTThreadUnblocking uses this to figure out when to clear pRec. */
+    RTTHREADSTATE volatile          enmRecState;
+    /** The thread is running inside the lock validator. */
+    bool volatile                   fInValidator;
+    /** Reserved for alignment purposes. */
+    bool                            afReserved[3];
     /** Number of registered write locks, mutexes and critsects that this thread owns. */
     int32_t volatile                cWriteLocks;
     /** Number of registered read locks that this thread owns, nesting included. */
     int32_t volatile                cReadLocks;
-    /** The thread is running inside the lock validator. */
-    bool volatile                   fInValidator;
-    /** Reserved for alignment purposes. */
-    bool                            afReserved[3];
     /** Bitmap indicating which entires are free (set) and allocated (clear). */
     uint32_t volatile               bmFreeShrdOwners;
+    /** Reserved for alignment purposes. */
+    uint32_t                        u32Reserved;
     /** Statically allocated shared owner records */
     RTLOCKVALRECSHRDOWN             aShrdOwners[32];
Index: /trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp	(revision 25647)
+++ /trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp	(revision 25648)
@@ -52,10 +52,15 @@
 *******************************************************************************/
 #include <iprt/semaphore.h>
+#include "internal/iprt.h"
+
 #include <iprt/assert.h>
-#include <iprt/alloc.h>
 #include <iprt/asm.h>
 #include <iprt/err.h>
+#include <iprt/lockvalidator.h>
+#include <iprt/mem.h>
 #include <iprt/time.h>
 #include "internal/magics.h"
+#include "internal/strict.h"
+
 
 #include <errno.h>
@@ -82,5 +87,5 @@
 {
     /** Magic value. */
-    intptr_t volatile   iMagic;
+    uint32_t volatile   u32Magic;
     /** The futex state variable.
      * -1 means signaled.
@@ -89,4 +94,10 @@
      */
     int32_t volatile    iState;
+#ifdef RTSEMEVENTMULTI_STRICT
+    /** Signallers. */
+    RTLOCKVALRECSHRD    Signallers;
+    /** Indicates that lock validation should be performed. */
+    bool volatile       fEverHadSignallers;
+#endif
 };
 
@@ -116,6 +127,12 @@
     if (pThis)
     {
-        pThis->iMagic = RTSEMEVENTMULTI_MAGIC;
-        pThis->iState = 0;
+        pThis->u32Magic = RTSEMEVENTMULTI_MAGIC;
+        pThis->iState   = 0;
+#ifdef RTSEMEVENTMULTI_STRICT
+        RTLockValidatorRecSharedInit(&pThis->Signallers,
+                                     NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY,
+                                     "RTSemEventMulti", pThis, true /*fSignaller*/);
+        pThis->fEverHadSignallers = false;
+#endif
         *pEventMultiSem = pThis;
         return VINF_SUCCESS;
@@ -131,5 +148,5 @@
      */
     struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
-    AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
                  VERR_INVALID_HANDLE);
 
@@ -137,5 +154,5 @@
      * Invalidate the semaphore and wake up anyone waiting on it.
      */
-    ASMAtomicWriteSize(&pThis->iMagic, RTSEMEVENTMULTI_MAGIC + 1);
+    ASMAtomicWriteSize(&pThis->u32Magic, RTSEMEVENTMULTI_MAGIC + 1);
     if (ASMAtomicXchgS32(&pThis->iState, -1) == 1)
     {
@@ -147,4 +164,7 @@
      * Free the semaphore memory and be gone.
      */
+#ifdef RTSEMEVENTMULTI_STRICT
+    RTLockValidatorRecSharedDelete(&pThis->Signallers);
+#endif
     RTMemFree(pThis);
     return VINF_SUCCESS;
@@ -158,6 +178,17 @@
      */
     struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
-    AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
                  VERR_INVALID_HANDLE);
+
+#ifdef RTSEMEVENTMULTI_STRICT
+    if (pThis->fEverHadSignallers)
+    {
+        int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD);
+        if (RT_FAILURE(rc9))
+            return rc9;
+    }
+#endif
+
+
     /*
      * Signal it.
@@ -181,5 +212,5 @@
      */
     struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
-    AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
                  VERR_INVALID_HANDLE);
 #ifdef RT_STRICT
@@ -198,9 +229,11 @@
 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume)
 {
+    PCRTLOCKVALSRCPOS pSrcPos = NULL;
+
     /*
      * Validate input.
      */
     struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;
-    AssertReturn(VALID_PTR(pThis) && pThis->iMagic == RTSEMEVENTMULTI_MAGIC,
+    AssertReturn(VALID_PTR(pThis) && pThis->u32Magic == RTSEMEVENTMULTI_MAGIC,
                  VERR_INVALID_HANDLE);
 
@@ -221,4 +254,5 @@
     if (cMillies != RT_INDEFINITE_WAIT)
     {
+        /* If the timeout is zero, then we're done. */
         if (!cMillies)
             return VERR_TIMEOUT;
@@ -232,4 +266,9 @@
      * The wait loop.
      */
+#ifdef RTSEMEVENTMULTI_STRICT
+    RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
+#else
+    RTTHREAD hThreadSelf = RTThreadSelf();
+#endif
     for (unsigned i = 0;; i++)
     {
@@ -252,6 +291,17 @@
                 ts.tv_nsec = i64Diff % 1000000000;
             }
+#ifdef RTSEMEVENTMULTI_STRICT
+            if (pThis->fEverHadSignallers)
+            {
+                int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false,
+                                                                RTTHREADSTATE_EVENT_MULTI, true);
+                if (RT_FAILURE(rc9))
+                    return rc9;
+            }
+#endif
+            RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true);
             long rc = sys_futex(&pThis->iState, FUTEX_WAIT, 1, pTimeout, NULL, 0);
-            if (RT_UNLIKELY(pThis->iMagic != RTSEMEVENTMULTI_MAGIC))
+            RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI);
+            if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC))
                 return VERR_SEM_DESTROYED;
             if (rc == 0)
@@ -263,5 +313,7 @@
             if (rc == -ETIMEDOUT)
             {
-/** @something is broken here. shows up every now and again in the ata code. Should try to run the timeout against RTTimeMilliTS to check that it's doing the right thing... */
+/** @todo something is broken here. shows up every now and again in the ata
+ *        code. Should try to run the timeout against RTTimeMilliTS to
+ *        check that it's doing the right thing... */
                 Assert(pTimeout);
                 return VERR_TIMEOUT;
@@ -303,5 +355,12 @@
 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
 {
-    /** @todo implement RTSemEventMultiSetSignaller on OS/2 */
+#ifdef RTSEMEVENTMULTI_STRICT
+    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+    AssertPtrReturnVoid(pThis);
+    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+    RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL);
+#endif
 }
 
@@ -309,4 +368,12 @@
 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
 {
+#ifdef RTSEMEVENTMULTI_STRICT
+    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+    AssertPtrReturnVoid(pThis);
+    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+    ASMAtomicWriteBool(&pThis->fEverHadSignallers, true);
+    RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL);
+#endif
 }
 
@@ -314,4 +381,11 @@
 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread)
 {
+#ifdef RTSEMEVENTMULTI_STRICT
+    struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem;
+    AssertPtrReturnVoid(pThis);
+    AssertReturnVoid(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC);
+
+    RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread);
+#endif
 }
 
Index: /trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
===================================================================
--- /trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp	(revision 25647)
+++ /trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp	(revision 25648)
@@ -124,5 +124,5 @@
                         RTLockValidatorRecSharedInit(&pThis->Signallers,
                                                      NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY,
-                                                     "RTSemEvent", pThis, true /*fSignaller*/);
+                                                     "RTSemEventMulti", pThis, true /*fSignaller*/);
                         pThis->fEverHadSignallers = false;
 #endif
Index: /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp	(revision 25647)
+++ /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp	(revision 25648)
@@ -45,4 +45,14 @@
 
 /*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+#define SECS_SIMPLE_TEST    1
+#define SECS_RACE_TEST      3
+#define TEST_SMALL_TIMEOUT  (  10*1000)
+#define TEST_LARGE_TIMEOUT  (  60*1000)
+#define TEST_DEBUG_TIMEOUT  (3600*1000)
+
+
+/*******************************************************************************
 *   Global Variables                                                           *
 *******************************************************************************/
@@ -52,4 +62,7 @@
 bool volatile               g_fDoNotSpin = false;
 
+/** Set when the main thread wishes to terminate the test. */
+bool volatile               g_fShutdown = false;
+/** The number of threads. */
 static uint32_t             g_cThreads;
 static uint32_t             g_iDeadlockThread;
@@ -63,6 +76,11 @@
 /** Multiple release event semaphore that is signalled by the main thread after
  * it has started all the threads. */
-static RTSEMEVENTMULTI      g_hThreadStarteEvt;
-
+static RTSEMEVENTMULTI      g_hThreadsStartedEvt;
+
+/** The number of threads that have called testThreadBlocking */
+static uint32_t volatile    g_cThreadsBlocking;
+/** Multiple release event semaphore that is signalled by the last thread to
+ * call testThreadBlocking.  testWaitForAllOtherThreadsToSleep waits on this. */
+static RTSEMEVENTMULTI      g_hThreadsBlockingEvt;
 
 /** When to stop testing. */
@@ -75,70 +93,91 @@
 
 /**
- * Spin until someone else has taken ownership of the critical section.
+ * Spin until the callback stops returning VERR_TRY_AGAIN.
  *
- * @returns true on success, false on abort.
- * @param   pCritSect   The critical section.
+ * @returns Callback result. VERR_TIMEOUT if too much time elapses.
+ * @param   pfnCallback     Callback for checking the state.
+ * @param   pvWhat          Callback parameter.
  */
-static bool testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
+static int testWaitForSomethingToBeOwned(int (*pfnCallback)(void *), void *pvWhat)
 {
     RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
-
-    unsigned iLoop = 0;
-    while (!RTCritSectIsOwned(pCritSect))
-    {
-        if (!RTCritSectIsInitialized(pCritSect))
-            return false;
-        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
-        iLoop++;
-    }
-    return true;
+    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsStartedEvt, TEST_SMALL_TIMEOUT));
+
+    uint64_t u64StartMS = RTTimeMilliTS();
+    for (unsigned iLoop = 0; ; iLoop++)
+    {
+        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
+
+        int rc = pfnCallback(pvWhat);
+        if (rc != VERR_TRY_AGAIN/* && !g_fDoNotSpin*/)
+        {
+            RTTEST_CHECK_RC_OK(g_hTest, rc);
+            return rc;
+        }
+
+        uint64_t cMsElapsed = RTTimeMilliTS() - u64StartMS;
+        if (!g_fDoNotSpin)
+            RTTEST_CHECK_RET(g_hTest, cMsElapsed <= TEST_SMALL_TIMEOUT, VERR_TIMEOUT);
+
+        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
+        RTThreadSleep(/*g_fDoNotSpin ? TEST_DEBUG_TIMEOUT :*/ iLoop > 256 ? 1 : 0);
+    }
+}
+
+
+static int testCheckIfCritSectIsOwned(void *pvWhat)
+{
+    PRTCRITSECT pCritSect = (PRTCRITSECT)pvWhat;
+    if (!RTCritSectIsInitialized(pCritSect))
+        return VERR_SEM_DESTROYED;
+    if (RTCritSectIsOwned(pCritSect))
+        return VINF_SUCCESS;
+    return VERR_TRY_AGAIN;
+}
+
+
+static int testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
+{
+    return testWaitForSomethingToBeOwned(testCheckIfCritSectIsOwned, pCritSect);
+}
+
+
+static int testCheckIfSemRWIsOwned(void *pvWhat)
+{
+    RTSEMRW hSemRW = (RTSEMRW)pvWhat;
+    if (RTSemRWGetWriteRecursion(hSemRW) > 0)
+        return VINF_SUCCESS;
+    if (RTSemRWGetReadCount(hSemRW) > 0)
+        return VINF_SUCCESS;
+    return VERR_TRY_AGAIN;
+}
+
+static int testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
+{
+    return testWaitForSomethingToBeOwned(testCheckIfSemRWIsOwned, hSemRW);
+}
+
+
+static int testCheckIfSemMutexIsOwned(void *pvWhat)
+{
+    RTSEMMUTEX hSemRW = (RTSEMMUTEX)pvWhat;
+    if (RTSemMutexIsOwned(hSemRW))
+        return VINF_SUCCESS;
+    return VERR_TRY_AGAIN;
+}
+
+static int testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex)
+{
+    return testWaitForSomethingToBeOwned(testCheckIfSemMutexIsOwned, hSemMutex);
 }
 
 
 /**
- * Spin until someone else has taken ownership (any kind) of the read-write
- * semaphore.
- *
- * @returns true on success, false on abort.
- * @param   hSemRW      The read-write semaphore.
+ * For reducing spin in testWaitForAllOtherThreadsToSleep.
  */
-static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
-{
-    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
-
-    unsigned iLoop = 0;
-    for (;;)
-    {
-        if (RTSemRWGetWriteRecursion(hSemRW) > 0)
-            return true;
-        if (RTSemRWGetReadCount(hSemRW) > 0)
-            return true;
-        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
-        iLoop++;
-    }
-    return true;
-}
-
-
-/**
- * Spin until someone else has taken ownership of the mutex semaphore.
- *
- * @returns true on success, false on abort.
- * @param   hSemMutex   The mutex sempahore.
- */
-static bool testWaitForSemMutexToBeOwned(RTSEMMUTEX hSemMutex)
-{
-    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
-
-    unsigned iLoop = 0;
-    while (!RTSemMutexIsOwned(hSemMutex))
-    {
-        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
-        iLoop++;
-    }
-    return true;
+static void testThreadBlocking(void)
+{
+    if (ASMAtomicIncU32(&g_cThreadsBlocking) == g_cThreads)
+        RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt));
 }
 
@@ -155,6 +194,7 @@
 static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn)
 {
+    testThreadBlocking();
     RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadStarteEvt, 10*1000));
+    RTTEST_CHECK_RC_OK(g_hTest, RTSemEventMultiWait(g_hThreadsBlockingEvt, TEST_SMALL_TIMEOUT));
 
     RTTHREAD hThreadSelf = RTThreadSelf();
@@ -207,16 +247,22 @@
                              && enmState != RTTHREADSTATE_INITIALIZING)
                         return VERR_INTERNAL_ERROR;
-                    RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop + iLoop > 256 ? 1 : 0);
+                    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
+                    RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop + iLoop > 256 ? 1 : 0);
+                    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
                     cWaitedOn++;
                 }
             }
+            RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
         }
 
         if (!cMissing && !cWaitedOn)
             break;
-        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iOuterLoop > 256 ? 1 : 0);
+        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
+        RTThreadSleep(g_fDoNotSpin ? TEST_DEBUG_TIMEOUT : iOuterLoop > 256 ? 1 : 0);
+        RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     }
 
     RTThreadSleep(0);                   /* fudge factor */
+    RTTEST_CHECK_RET(g_hTest, !g_fShutdown, VERR_INTERNAL_ERROR);
     return VINF_SUCCESS;
 }
@@ -232,5 +278,5 @@
 static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread)
 {
-    RTSemEventMultiReset(g_hThreadStarteEvt);
+    RTSemEventMultiReset(g_hThreadsStartedEvt);
 
     for (uint32_t i = 0; i < RT_ELEMENTS(g_ahThreads); i++)
@@ -247,5 +293,5 @@
     }
 
-    RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThreadStarteEvt), rcCheck);
+    RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), rcCheck);
     return rc;
 }
@@ -276,13 +322,13 @@
 
 
-static void testIt(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs, PFNRTTHREAD pfnThread, const char *pszName)
+static void testIt(uint32_t cThreads, uint32_t cSecs, bool fLoops, PFNRTTHREAD pfnThread, const char *pszName)
 {
     /*
      * Init test.
      */
-    if (cSecs)
-        RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs * cPasses);
+    if (cSecs > 0)
+        RTTestSubF(g_hTest, "%s, %u threads, %u secs", pszName, cThreads, cSecs);
     else
-        RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
+        RTTestSubF(g_hTest, "%s, %u threads, single pass", pszName, cThreads);
 
     RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
@@ -290,4 +336,5 @@
 
     g_cThreads = cThreads;
+    g_fShutdown = false;
 
     for (uint32_t i = 0; i < cThreads; i++)
@@ -299,32 +346,49 @@
     RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventCreate(&g_hSemEvt), VINF_SUCCESS);
     RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hSemEvtMulti), VINF_SUCCESS);
-    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadStarteEvt), VINF_SUCCESS);
+    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsStartedEvt), VINF_SUCCESS);
+    RTTEST_CHECK_RC_RETV(g_hTest, RTSemEventMultiCreate(&g_hThreadsBlockingEvt), VINF_SUCCESS);
 
     /*
      * The test loop.
      */
+    uint32_t cPasses    = 0;
     uint32_t cLoops     = 0;
     uint32_t cDeadlocks = 0;
     uint32_t cErrors    = RTTestErrorCount(g_hTest);
-    for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
-    {
-        g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
-        g_cLoops          = 0;
-        g_cDeadlocks      = 0;
-        g_NanoTSStop      = cSecs ? RTTimeNanoTS() + cSecs * UINT64_C(1000000000) : 0;
+    uint64_t uStartNS   = RTTimeNanoTS();
+    g_NanoTSStop        = uStartNS + cSecs * UINT64_C(1000000000);
+    do
+    {
+        g_iDeadlockThread  = (cThreads - 1 + cPasses) % cThreads;
+        g_cLoops           = 0;
+        g_cDeadlocks       = 0;
+        g_cThreadsBlocking = 0;
+        RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hThreadsBlockingEvt), VINF_SUCCESS);
 
         int rc = testStartThreads(cThreads, pfnThread);
         if (RT_SUCCESS(rc))
-            testWaitForThreads(30*1000 + cSecs*1000, true);
-
-        RTTEST_CHECK(g_hTest, !cSecs || g_cLoops > 0);
+        {
+            testWaitForThreads(TEST_LARGE_TIMEOUT + cSecs*1000, true);
+            if (g_fDoNotSpin && RTTestErrorCount(g_hTest) != cErrors)
+                testWaitForThreads(TEST_DEBUG_TIMEOUT, true);
+        }
+
+        RTTEST_CHECK(g_hTest, !fLoops || g_cLoops > 0);
         cLoops += g_cLoops;
-        RTTEST_CHECK(g_hTest, !cSecs || g_cDeadlocks > 0);
+        RTTEST_CHECK(g_hTest, !fLoops || g_cDeadlocks > 0);
         cDeadlocks += g_cDeadlocks;
-    }
+        cPasses++;
+    } while (   RTTestErrorCount(g_hTest) == cErrors
+             && !fLoops
+             && RTTimeNanoTS() < g_NanoTSStop);
 
     /*
      * Cleanup.
      */
+    ASMAtomicWriteBool(&g_fShutdown, true);
+    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsBlockingEvt), VINF_SUCCESS);
+    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hThreadsStartedEvt), VINF_SUCCESS);
+    RTThreadSleep(RTTestErrorCount(g_hTest) == cErrors ? 0 : 50);
+
     for (uint32_t i = 0; i < cThreads; i++)
     {
@@ -335,7 +399,8 @@
     RTTEST_CHECK_RC(g_hTest, RTSemEventDestroy(g_hSemEvt), VINF_SUCCESS);
     RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hSemEvtMulti), VINF_SUCCESS);
-    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadStarteEvt), VINF_SUCCESS);
-
-    testWaitForThreads(10*1000, false);
+    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsStartedEvt), VINF_SUCCESS);
+    RTTEST_CHECK_RC(g_hTest, RTSemEventMultiDestroy(g_hThreadsBlockingEvt), VINF_SUCCESS);
+
+    testWaitForThreads(TEST_SMALL_TIMEOUT, false);
 
     /*
@@ -343,6 +408,11 @@
      */
     if (cSecs)
-        RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
-                     cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
+    {
+        if (fLoops)
+            RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cLoops=%u cDeadlocks=%u (%u%%)\n",
+                         cLoops, cDeadlocks, cLoops ? cDeadlocks * 100 / cLoops : 0);
+        else
+            RTTestPrintf(g_hTest,  RTTESTLVL_ALWAYS, "cPasses=%u\n", cPasses);
+    }
 }
 
@@ -357,9 +427,12 @@
     if (i & 1)
         RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
-    if (testWaitForCritSectToBeOwned(pNext))
+    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
     {
         int rc;
         if (i != g_iDeadlockThread)
+        {
+            testThreadBlocking();
             RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
+        }
         else
         {
@@ -379,7 +452,7 @@
 
 
-static void test1(uint32_t cThreads, uint32_t cPasses)
-{
-    testIt(cThreads, cPasses, 0, test1Thread, "critsect");
+static void test1(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, false, test1Thread, "critsect");
 }
 
@@ -400,8 +473,11 @@
     else
         RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
-    if (testWaitForSemRWToBeOwned(hNext))
+    if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext)))
     {
         if (i != g_iDeadlockThread)
+        {
+            testThreadBlocking();
             RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
+        }
         else
         {
@@ -432,7 +508,7 @@
 
 
-static void test2(uint32_t cThreads, uint32_t cPasses)
-{
-    testIt(cThreads, cPasses, 0, test2Thread, "read-write");
+static void test2(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, false, test2Thread, "read-write");
 }
 
@@ -449,9 +525,9 @@
     else
         RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
-    if (testWaitForSemRWToBeOwned(hNext))
+    if (RT_SUCCESS(testWaitForSemRWToBeOwned(hNext)))
     {
         do
         {
-            rc = RTSemRWRequestWrite(hNext, 60*1000);
+            rc = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT);
             if (rc != VINF_SUCCESS && rc != VERR_SEM_LV_DEADLOCK && rc != VERR_SEM_LV_ILLEGAL_UPGRADE)
             {
@@ -479,7 +555,7 @@
 
 
-static void test3(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
-{
-    testIt(cThreads, cPasses, cSecs, test3Thread, "read-write race");
+static void test3(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, true, test3Thread, "read-write race");
 }
 
@@ -493,5 +569,5 @@
     do
     {
-        int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, 60*1000); /* ugly ;-) */
+        int rc1 = (i & 1 ? RTSemRWRequestWrite : RTSemRWRequestRead)(hMine, TEST_SMALL_TIMEOUT); /* ugly ;-) */
         RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
         if (rc1 != VINF_SUCCESS && rc1 != VERR_SEM_LV_DEADLOCK && rc1 != VERR_SEM_LV_ILLEGAL_UPGRADE)
@@ -504,5 +580,5 @@
             for (unsigned iInner = 0; iInner < 4; iInner++)
             {
-                int rc2 = RTSemRWRequestWrite(hNext, 60*1000);
+                int rc2 = RTSemRWRequestWrite(hNext, TEST_SMALL_TIMEOUT);
                 if (rc2 != VINF_SUCCESS && rc2 != VERR_SEM_LV_DEADLOCK && rc2 != VERR_SEM_LV_ILLEGAL_UPGRADE)
                 {
@@ -535,7 +611,7 @@
 
 
-static void test4(uint32_t cThreads, uint32_t cPasses, uint32_t cSecs)
-{
-    testIt(cThreads, cPasses, cSecs, test4Thread, "read-write race v2");
+static void test4(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, true, test4Thread, "read-write race v2");
 }
 
@@ -550,9 +626,12 @@
     if (i & 1)
         RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS);
-    if (testWaitForSemMutexToBeOwned(hNext))
+    if (RT_SUCCESS(testWaitForSemMutexToBeOwned(hNext)))
     {
         int rc;
         if (i != g_iDeadlockThread)
+        {
+            testThreadBlocking();
             RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
+        }
         else
         {
@@ -572,7 +651,7 @@
 
 
-static void test5(uint32_t cThreads, uint32_t cPasses)
-{
-    testIt(cThreads, cPasses, 0, test5Thread, "mutex");
+static void test5(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, false, test5Thread, "mutex");
 }
 
@@ -587,9 +666,10 @@
     if (i & 1)
         RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
-    if (testWaitForCritSectToBeOwned(pNext))
+    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
     {
         int rc;
         if (i != g_iDeadlockThread)
         {
+            testThreadBlocking();
             RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
             RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
@@ -606,9 +686,9 @@
                     RTSemEventAddSignaller(g_hSemEvt, g_ahThreads[iThread]);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VERR_SEM_LV_DEADLOCK);
+                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
                 RTTEST_CHECK_RC(g_hTest, RTSemEventSignal(g_hSemEvt), VINF_SUCCESS);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, 10*1000), VINF_SUCCESS);
+                RTTEST_CHECK_RC(g_hTest, RTSemEventWait(g_hSemEvt, TEST_SMALL_TIMEOUT), VINF_SUCCESS);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
                 RTSemEventSetSignaller(g_hSemEvt, NIL_RTTHREAD);
@@ -624,7 +704,7 @@
 
 
-static void test6(uint32_t cThreads, uint32_t cPasses)
-{
-    testIt(cThreads, cPasses, 0, test6Thread, "event");
+static void test6(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, false, test6Thread, "event");
 }
 
@@ -639,9 +719,10 @@
     if (i & 1)
         RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS);
-    if (testWaitForCritSectToBeOwned(pNext))
+    if (RT_SUCCESS(testWaitForCritSectToBeOwned(pNext)))
     {
         int rc;
         if (i != g_iDeadlockThread)
         {
+            testThreadBlocking();
             RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
             RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
@@ -659,9 +740,9 @@
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
                 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hSemEvtMulti), VINF_SUCCESS);
-                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VERR_SEM_LV_DEADLOCK);
+                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VERR_SEM_LV_DEADLOCK);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
                 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hSemEvtMulti), VINF_SUCCESS);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
-                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VINF_SUCCESS);
+                RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, TEST_SMALL_TIMEOUT), VINF_SUCCESS);
                 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
                 RTSemEventMultiSetSignaller(g_hSemEvtMulti, NIL_RTTHREAD);
@@ -677,8 +758,9 @@
 
 
-static void test7(uint32_t cThreads, uint32_t cPasses)
-{
-    testIt(cThreads, cPasses, 0, test7Thread, "event multi");
-}
+static void test7(uint32_t cThreads, uint32_t cSecs)
+{
+    testIt(cThreads, cSecs, false, test7Thread, "event multi");
+}
+
 
 static bool testIsLockValidationCompiledIn(void)
@@ -756,66 +838,64 @@
 
     /*
-     * Some initial tests with verbose output.
+     * Some initial tests with verbose output (all single pass).
      */
-#if 1
-    test1(3, 1);
-    test2(1, 1);
-    test2(3, 1);
-    test5(3, 1);
-    test6(3, 1);
-#endif
-    test7(3, 1);
+    test1(3, 0);
+    test2(1, 0);
+    test2(3, 0);
+    test5(3, 0);
+    test6(3, 0);
+    test7(3, 0);
 
     /*
-     * More thorough testing without noisy output.
+     * If successful, perform more thorough testing without noisy output.
      */
-    RTLockValidatorSetQuiet(true);
-#if 1
-    test1( 2, 256);                     /* 256 * 4ms = 1s (approx); 4ms == fudge factor */
-    test1( 3, 256);
-    test1( 7, 256);
-    test1(10, 256);
-    test1(15, 256);
-    test1(30, 256);
-
-    test2( 1, 256);
-    test2( 2, 256);
-    test2( 3, 256);
-    test2( 7, 256);
-    test2(10, 256);
-    test2(15, 256);
-    test2(30, 256);
-
-    test3( 2,  1,  2);
-    test3(10,  1,  2);
-
-    test4( 2,  1,  2);
-    test4( 6,  1,  2);
-    test4(10,  1, 10);
-    test4(30,  1, 10);
-
-    test5( 2, 256);
-    test5( 3, 256);
-    test5( 7, 256);
-    test5(10, 256);
-    test5(15, 256);
-    test5(30, 256);
-
-    test6( 2, 256);
-    test6( 3, 256);
-    test6( 7, 256);
-    test6(10, 256);
-    test6(15, 256);
-    test6(30, 256);
-#endif
-
-#if 1
-    test7( 2, 256);
-    test7( 3, 256);
-    test7( 7, 256);
-    test7(10, 256);
-    test7(15, 256);
-    test7(30, 256);
-#endif
+    if (RTTestErrorCount(g_hTest) == 0)
+    {
+        RTLockValidatorSetQuiet(true);
+
+        test1( 2, SECS_SIMPLE_TEST);
+        test1( 3, SECS_SIMPLE_TEST);
+        test1( 7, SECS_SIMPLE_TEST);
+        test1(10, SECS_SIMPLE_TEST);
+        test1(15, SECS_SIMPLE_TEST);
+        test1(30, SECS_SIMPLE_TEST);
+
+        test2( 1, SECS_SIMPLE_TEST);
+        test2( 2, SECS_SIMPLE_TEST);
+        test2( 3, SECS_SIMPLE_TEST);
+        test2( 7, SECS_SIMPLE_TEST);
+        test2(10, SECS_SIMPLE_TEST);
+        test2(15, SECS_SIMPLE_TEST);
+        test2(30, SECS_SIMPLE_TEST);
+
+        test3( 2, SECS_SIMPLE_TEST);
+        test3(10, SECS_SIMPLE_TEST);
+
+        test4( 2, SECS_RACE_TEST);
+        test4( 6, SECS_RACE_TEST);
+        test4(10, SECS_RACE_TEST);
+        test4(30, SECS_RACE_TEST);
+
+        test5( 2, SECS_RACE_TEST);
+        test5( 3, SECS_RACE_TEST);
+        test5( 7, SECS_RACE_TEST);
+        test5(10, SECS_RACE_TEST);
+        test5(15, SECS_RACE_TEST);
+        test5(30, SECS_RACE_TEST);
+
+        test6( 2, SECS_SIMPLE_TEST);
+        test6( 3, SECS_SIMPLE_TEST);
+        test6( 7, SECS_SIMPLE_TEST);
+        test6(10, SECS_SIMPLE_TEST);
+        test6(15, SECS_SIMPLE_TEST);
+        test6(30, SECS_SIMPLE_TEST);
+
+        test7( 2, SECS_SIMPLE_TEST);
+        test7( 3, SECS_SIMPLE_TEST);
+        test7( 7, SECS_SIMPLE_TEST);
+        test7(10, SECS_SIMPLE_TEST);
+        test7(15, SECS_SIMPLE_TEST);
+        test7(30, SECS_SIMPLE_TEST);
+    }
 
     return RTTestSummaryAndDestroy(g_hTest);
