Index: /trunk/include/iprt/lockvalidator.h
===================================================================
--- /trunk/include/iprt/lockvalidator.h	(revision 25616)
+++ /trunk/include/iprt/lockvalidator.h	(revision 25617)
@@ -637,4 +637,12 @@
 RTDECL(void) RTLockValidatorReadLockDec(RTTHREAD Thread);
 
+/**
+ * Query which lock the specified thread is waiting on.
+ *
+ * @returns The lock handle value or NULL.
+ * @param   hThread     The thread in question.
+ */
+RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread);
+
 
 
Index: /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25616)
+++ /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25617)
@@ -86,4 +86,17 @@
 /** Pointer to a deadlock detction stack. */
 typedef RTLOCKVALDDSTACK *PRTLOCKVALDDSTACK;
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Macro that asserts that a pointer is aligned correctly.
+ * Only used when fighting bugs. */
+#if 1
+# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   \
+    AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));
+#else
+# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   do { } while (0)
+#endif
 
 
@@ -121,5 +134,7 @@
 DECL_FORCE_INLINE(PRTLOCKVALRECUNION) rtLockValidatorReadRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec)
 {
-    return (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec);
+    PRTLOCKVALRECUNION p = (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec);
+    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
+    return p;
 }
 
@@ -128,4 +143,5 @@
 DECL_FORCE_INLINE(void) rtLockValidatorWriteRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec, PRTLOCKVALRECUNION pRecNew)
 {
+    RTLOCKVAL_ASSERT_PTR_ALIGN(pRecNew);
     ASMAtomicWritePtr((void * volatile *)ppRec, pRecNew);
 }
@@ -135,5 +151,7 @@
 DECL_FORCE_INLINE(PRTTHREADINT) rtLockValidatorReadThreadHandle(RTTHREAD volatile *phThread)
 {
-    return (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread);
+    PRTTHREADINT p = (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread);
+    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
+    return p;
 }
 
@@ -142,5 +160,7 @@
 DECL_FORCE_INLINE(PRTLOCKVALRECSHRDOWN) rtLockValidatorUoReadSharedOwner(PRTLOCKVALRECSHRDOWN volatile *ppOwner)
 {
-    return (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner);
+    PRTLOCKVALRECSHRDOWN p = (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner);
+    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
+    return p;
 }
 
@@ -456,37 +476,4 @@
 
 /**
- * Worker for rtLockValidatorDoDeadlockCheck that checks if there is more work
- * to be done during unwind.
- *
- * @returns true if there is more work left for this lock, false if not.
- * @param   pRec            The current record.
- * @param   iEntry          The current index.
- * @param   pFirstSibling   The first record we examined.
- */
-DECL_FORCE_INLINE(bool) rtLockValidatorDdMoreWorkLeft(PRTLOCKVALRECUNION pRec, uint32_t iEntry, PRTLOCKVALRECUNION pFirstSibling)
-{
-    PRTLOCKVALRECUNION pSibling;
-
-    switch (pRec->Core.u32Magic)
-    {
-        case RTLOCKVALRECEXCL_MAGIC:
-            pSibling = pRec->Excl.pSibling;
-            break;
-
-        case RTLOCKVALRECSHRD_MAGIC:
-            if (iEntry + 1 < pRec->Shared.cAllocated)
-                return true;
-            pSibling = pRec->Excl.pSibling;
-            break;
-
-        default:
-            return false;
-    }
-    return pSibling != NULL
-        && pSibling != pFirstSibling;
-}
-
-
-/**
  * Worker for rtLockValidatorDeadlockDetection that does the actual deadlock
  * detection.
@@ -519,4 +506,6 @@
          * Process the current record.
          */
+        RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
+
         /* Find the next relevant owner thread. */
         PRTTHREADINT pNextThread;
@@ -526,16 +515,16 @@
                 Assert(iEntry == UINT32_MAX);
                 pNextThread = rtLockValidatorReadThreadHandle(&pRec->Excl.hThread);
-                if (    pNextThread
-                    &&  pNextThread->u32Magic == RTTHREADINT_MAGIC
-                    &&  !RTTHREAD_IS_SLEEPING(pNextThread->enmState)
-                    &&  pNextThread != pThreadSelf)
-                    pNextThread = NIL_RTTHREAD;
-
-                if (    pNextThread == NIL_RTTHREAD
-                    &&  pRec->Excl.pSibling
-                    &&  pRec->Excl.pSibling != pFirstSibling)
+                if (    !pNextThread
+                    ||  (   pNextThread != pThreadSelf
+                         && (   pNextThread->u32Magic != RTTHREADINT_MAGIC
+                             || !RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread)) )
+                        )
+                   )
                 {
                     pRec = pRec->Excl.pSibling;
-                    continue;
+                    if (    pRec
+                        &&  pRec != pFirstSibling)
+                        continue;
+                    pNextThread = NIL_RTTHREAD;
                 }
                 break;
@@ -580,5 +569,5 @@
                             {
                                 if (   pNextThread->u32Magic == RTTHREADINT_MAGIC
-                                    && (   RTTHREAD_IS_SLEEPING(pNextThread->enmState)
+                                    && (   RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread))
                                         || pNextThread == pThreadSelf))
                                     break;
@@ -589,16 +578,17 @@
                             Assert(!pEntry || pEntry->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC_DEAD);
                     }
-                    if (pNextThread == NIL_RTTHREAD)
+                    if (pNextThread != NIL_RTTHREAD)
                         break;
                 }
 
                 /* Advance to the next sibling, if any. */
-                if (   pRec->Shared.pSibling != NULL
-                    && pRec->Shared.pSibling != pFirstSibling)
+                pRec = pRec->Shared.pSibling;
+                if (   pRec != NULL
+                    && pRec != pFirstSibling)
                 {
-                    pRec = pRec->Shared.pSibling;
                     iEntry = UINT32_MAX;
                     continue;
                 }
+                Assert(pNextThread == NIL_RTTHREAD);
                 break;
 
@@ -673,17 +663,37 @@
                     return VINF_SUCCESS;
                 i--;
-
-                /* examine it. */
-                pRec            = pStack->a[i].pRec;
-                pFirstSibling   = pStack->a[i].pFirstSibling;
-                iEntry          = pStack->a[i].iEntry;
-                if (rtLockValidatorDdMoreWorkLeft(pRec, iEntry, pFirstSibling))
+                pRec    = pStack->a[i].pRec;
+                iEntry  = pStack->a[i].iEntry;
+
+                /* Examine it. */
+                uint32_t u32Magic = pRec->Core.u32Magic;
+                if (u32Magic == RTLOCKVALRECEXCL_MAGIC)
+                    pRec = pRec->Excl.pSibling;
+                else if (u32Magic == RTLOCKVALRECSHRD_MAGIC)
                 {
-                    enmState    = pStack->a[i].enmState;
-                    pThread     = pStack->a[i].pThread;
-                    pStack->c   = i;
-                    break;
+                    if (iEntry + 1 < pRec->Shared.cAllocated)
+                        break;  /* continue processing this record. */
+                    pRec = pRec->Shared.pSibling;
                 }
+                else
+                {
+                    Assert(   u32Magic == RTLOCKVALRECEXCL_MAGIC_DEAD
+                           || u32Magic == RTLOCKVALRECSHRD_MAGIC_DEAD);
+                    continue;
+                }
+
+                /* Any next record to advance to? */
+                if (   !pRec
+                    || pRec == pStack->a[i].pFirstSibling)
+                    continue;
+                iEntry = UINT32_MAX;
+                break;
             }
+
+            /* Restore the rest of the state and update the stack. */
+            pFirstSibling   = pStack->a[i].pFirstSibling;
+            enmState        = pStack->a[i].enmState;
+            pThread         = pStack->a[i].pThread;
+            pStack->c       = i;
         }
         /* else: see if there is another thread to check for this lock. */
@@ -888,4 +898,7 @@
                                         uint32_t uSubClass, const char *pszName, void *hLock)
 {
+    RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
+    RTLOCKVAL_ASSERT_PTR_ALIGN(hLock);
+
     pRec->Core.u32Magic = RTLOCKVALRECEXCL_MAGIC;
     pRec->fEnabled      = RTLockValidatorIsEnabled();
@@ -1187,4 +1200,7 @@
                                           uint32_t uSubClass, const char *pszName, void *hLock)
 {
+    RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
+    RTLOCKVAL_ASSERT_PTR_ALIGN(hLock);
+
     pRec->Core.u32Magic = RTLOCKVALRECSHRD_MAGIC;
     pRec->uSubClass     = uSubClass;
@@ -1770,4 +1786,49 @@
 
 
+RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread)
+{
+    void           *pvLock  = NULL;
+    PRTTHREADINT    pThread = rtThreadGet(hThread);
+    if (pThread)
+    {
+        RTTHREADSTATE enmState = rtThreadGetState(pThread);
+        if (RTTHREAD_IS_SLEEPING(enmState))
+        {
+            rtLockValidatorSerializeDetectionEnter();
+
+            enmState = rtThreadGetState(pThread);
+            if (RTTHREAD_IS_SLEEPING(enmState))
+            {
+                PRTLOCKVALRECUNION pRec = rtLockValidatorReadRecUnionPtr(&pThread->LockValidator.pRec);
+                if (pRec)
+                {
+                    switch (pRec->Core.u32Magic)
+                    {
+                        case RTLOCKVALRECEXCL_MAGIC:
+                            pvLock = pRec->Excl.hLock;
+                            break;
+
+                        case RTLOCKVALRECSHRDOWN_MAGIC:
+                            pRec = (PRTLOCKVALRECUNION)pRec->ShrdOwner.pSharedRec;
+                            if (!pRec || pRec->Core.u32Magic != RTLOCKVALRECSHRD_MAGIC)
+                                break;
+                        case RTLOCKVALRECSHRD_MAGIC:
+                            pvLock = pRec->Shared.hLock;
+                            break;
+                    }
+                    if (RTThreadGetState(pThread) != enmState)
+                        pvLock = NULL;
+                }
+            }
+
+            rtLockValidatorSerializeDetectionLeave();
+        }
+        rtThreadRelease(pThread);
+    }
+    return pvLock;
+}
+RT_EXPORT_SYMBOL(RTLockValidatorQueryBlocking);
+
+
 RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled)
 {
Index: /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp	(revision 25616)
+++ /trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp	(revision 25617)
@@ -46,9 +46,14 @@
 *   Global Variables                                                           *
 *******************************************************************************/
+/** The testcase handle. */
 static RTTEST       g_hTest;
-
-static uint32_t     g_cThreads;
-static RTTHREAD     g_ahThreads[32];
-static RTCRITSECT   g_aCritSects[32];
+/** Flip this in the debugger to get some peace to single step wild code. */
+bool volatile       g_fDoNotSpin = false;
+
+static uint32_t             g_cThreads;
+static uint32_t volatile    g_iDeadlockThread;
+static RTTHREAD             g_ahThreads[32];
+static RTCRITSECT           g_aCritSects[32];
+static RTSEMRW              g_ahSemRWs[32];
 
 
@@ -66,5 +71,5 @@
         if (!RTCritSectIsInitialized(pCritSect))
             return false;
-        RTThreadSleep(iLoop > 256 ? 1 : 0);
+        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
         iLoop++;
     }
@@ -74,20 +79,137 @@
 
 /**
+ * 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.
+ */
+static bool testWaitForSemRWToBeOwned(RTSEMRW hSemRW)
+{
+    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
+    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;
+}
+
+
+/**
  * Waits for a thread to enter a sleeping state.
  *
  * @returns true on success, false on abort.
- * @param   hThread     The thread.
- */
-static bool testWaitForThreadToSleep(RTTHREAD hThread)
-{
+ * @param   hThread             The thread.
+ * @param   enmDesiredState     The desired thread sleep state.
+ * @param   pvLock              The lock it should be sleeping on.
+ */
+static bool testWaitForThreadToSleep(RTTHREAD hThread, RTTHREADSTATE enmDesiredState, void *pvLock)
+{
+    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
     for (unsigned iLoop = 0; ; iLoop++)
     {
         RTTHREADSTATE enmState = RTThreadGetState(hThread);
         if (RTTHREAD_IS_SLEEPING(enmState))
-            return true;
-        if (enmState != RTTHREADSTATE_RUNNING)
+        {
+            if (   enmState == enmDesiredState
+                && (   !pvLock
+                    || pvLock == RTLockValidatorQueryBlocking(hThread)))
+                return true;
+        }
+        else if (enmState != RTTHREADSTATE_RUNNING)
             return false;
-        RTThreadSleep(iLoop > 256 ? 1 : 0);
-    }
+        RTThreadSleep(g_fDoNotSpin ? 3600*1000 : iLoop > 256 ? 1 : 0);
+    }
+}
+
+
+/**
+ * Waits for all the other threads to enter sleeping states.
+ *
+ * @returns VINF_SUCCESS on success, VERR_INTERNAL_ERROR on failure.
+ * @param   enmDesiredState     The desired thread sleep state.
+ * @param   cWaitOn             The distance to the lock they'll be waiting on,
+ *                              the lock type is derived from the desired state.
+ *                              UINT32_MAX means no special lock.
+ */
+static int testWaitForAllOtherThreadsToSleep(RTTHREADSTATE enmDesiredState, uint32_t cWaitOn)
+{
+    RTTHREAD hThreadSelf = RTThreadSelf();
+    for (uint32_t i = 0; i < g_cThreads; i++)
+    {
+        RTTHREAD hThread = g_ahThreads[i];
+        if (    hThread != NIL_RTTHREAD
+            &&  hThread != hThreadSelf)
+        {
+            void *pvLock = NULL;
+            if (cWaitOn != UINT32_MAX)
+            {
+                uint32_t j = (i + cWaitOn) % g_cThreads;
+                switch (enmDesiredState)
+                {
+                    case RTTHREADSTATE_CRITSECT:    pvLock = &g_aCritSects[j]; break;
+                    case RTTHREADSTATE_RW_WRITE:
+                    case RTTHREADSTATE_RW_READ:     pvLock = g_ahSemRWs[j]; break;
+                    default: break;
+                }
+            }
+            bool fRet = testWaitForThreadToSleep(hThread, enmDesiredState, pvLock);
+            if (!fRet)
+                return VERR_INTERNAL_ERROR;
+        }
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker that starts the threads.
+ *
+ * @returns Same as RTThreadCreate.
+ * @param   cThreads            The number of threads to start.
+ * @param   pfnThread           Thread function.
+ */
+static int testStartThreads(uint32_t cThreads, PFNRTTHREAD pfnThread)
+{
+    uint32_t i;
+    for (i = 0; i < RT_ELEMENTS(g_ahThreads); i++)
+        g_ahThreads[i] = NIL_RTTHREAD;
+
+    for (i = 0; i < cThreads; i++)
+        RTTEST_CHECK_RC_OK_RET(g_hTest,
+                               RTThreadCreateF(&g_ahThreads[i], pfnThread, (void *)(uintptr_t)i, 0,
+                                               RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "thread-%02u", i),
+                               rcCheck);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker that waits for the threads to complete.
+ *
+ * @param   cMillies            How long to wait for each.
+ * @param   fStopOnError        Whether to stop on error and heed the thread
+ *                              return status.
+ */
+static void testWaitForThreads(uint32_t cMillies, bool fStopOnError)
+{
+    uint32_t i = RT_ELEMENTS(g_ahThreads);
+    while (i-- > 0)
+        if (g_ahThreads[i] != NIL_RTTHREAD)
+        {
+            int rcThread;
+            int rc2;
+            RTTEST_CHECK_RC_OK(g_hTest, rc2 = RTThreadWait(g_ahThreads[i], cMillies, &rcThread));
+            if (RT_SUCCESS(rc2))
+                g_ahThreads[i] = NIL_RTTHREAD;
+            if (fStopOnError && (RT_FAILURE(rc2) || RT_FAILURE(rcThread)))
+                return;
+        }
 }
 
@@ -103,13 +225,13 @@
     {
         int rc;
-        if (i != g_cThreads - 1)
+        if (i != g_iDeadlockThread)
             RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
         else
         {
-            /* the last thread triggers the deadlock. */
-            for (unsigned i = 0; i < g_cThreads - 1; i++)
-                RTTEST_CHECK_RET(g_hTest, testWaitForThreadToSleep(g_ahThreads[i]), VINF_SUCCESS);
-            RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK);
+            RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_CRITSECT, 1));
+            if (RT_SUCCESS(rc))
+                RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK);
         }
+        RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
         if (RT_SUCCESS(rc))
             RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(pNext), VINF_SUCCESS);
@@ -120,42 +242,90 @@
 
 
-static void test1(uint32_t cThreads)
-{
-    uint32_t i;
-    RTTestSubF(g_hTest, "critsect deadlock with %u threads", cThreads);
+static DECLCALLBACK(int) test2Thread(RTTHREAD ThreadSelf, void *pvUser)
+{
+    uintptr_t       i     = (uintptr_t)pvUser;
+    RTSEMRW         hMine = g_ahSemRWs[i];
+    RTSEMRW         hNext = g_ahSemRWs[(i + 1) % g_cThreads];
+    int             rc;
+
+    if (i & 1)
+        RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestWrite(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
+    else
+        RTTEST_CHECK_RC_RET(g_hTest, RTSemRWRequestRead(hMine, RT_INDEFINITE_WAIT), VINF_SUCCESS, rcCheck);
+    if (testWaitForSemRWToBeOwned(hNext))
+    {
+        if (i != g_iDeadlockThread)
+            RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VINF_SUCCESS);
+        else
+        {
+            RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_RW_WRITE, 1));
+            if (RT_SUCCESS(rc))
+            {
+                if (g_cThreads > 1)
+                    RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_DEADLOCK);
+                else
+                    RTTEST_CHECK_RC(g_hTest, rc = RTSemRWRequestWrite(hNext, RT_INDEFINITE_WAIT), VERR_SEM_LV_ILLEGAL_UPGRADE);
+            }
+        }
+        RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
+        if (RT_SUCCESS(rc))
+            RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hNext), VINF_SUCCESS);
+    }
+    if (i & 1)
+        RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseWrite(hMine), VINF_SUCCESS);
+    else
+        RTTEST_CHECK_RC(g_hTest, RTSemRWReleaseRead(hMine), VINF_SUCCESS);
+    RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING);
+    return VINF_SUCCESS;
+}
+
+
+static void testIt(uint32_t cThreads, uint32_t cPasses, PFNRTTHREAD pfnThread, const char *pszName)
+{
+    RTTestSubF(g_hTest, "%s, %u threads, %u passes", pszName, cThreads, cPasses);
+
     RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
     RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads);
 
     g_cThreads = cThreads;
-    for (i = 0; i < cThreads; i++)
+    g_iDeadlockThread = cThreads - 1;
+
+    for (uint32_t i = 0; i < cThreads; i++)
+    {
         RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
-
-    for (i = 0; i < cThreads && g_ahThreads[i]; i++)
-        g_ahThreads[i] = NIL_RTTHREAD;
-    int rc = VINF_SUCCESS;
-    for (i = 0; i < cThreads && RT_SUCCESS(rc); i++)
-        RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadCreateF(&g_ahThreads[i], test1Thread, (void *)(uintptr_t)i, 0,
-                                                         RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1-%02u", i));
-    if (RT_SUCCESS(rc))
-    {
-        int rc2 = VINF_SUCCESS;
-        i = cThreads;
-        while (i-- > 0 && RT_SUCCESS(rc) && RT_SUCCESS(rc2))
-        {
-            RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 30*1000, &rc2));
-            if (RT_SUCCESS(rc))
-                g_ahThreads[i] = NIL_RTTHREAD;
-        }
+        RTTEST_CHECK_RC_RETV(g_hTest, RTSemRWCreate(&g_ahSemRWs[i]), VINF_SUCCESS);
+    }
+
+    uint32_t cErrors = RTTestErrorCount(g_hTest);
+    for (uint32_t iPass = 0; iPass < cPasses && RTTestErrorCount(g_hTest) == cErrors; iPass++)
+    {
+#if 0 /** @todo figure why this ain't working for either of the two tests! */
+        g_iDeadlockThread = (cThreads - 1 + iPass) % cThreads;
+#endif
+        int rc = testStartThreads(cThreads, pfnThread);
+        if (RT_SUCCESS(rc))
+            testWaitForThreads(30*1000, true);
     }
 
     for (uint32_t i = 0; i < cThreads; i++)
-        RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
-    for (uint32_t i = 0; i < cThreads; i++)
-        if (g_ahThreads[i] != NIL_RTTHREAD)
-        {
-            RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 10*1000, NULL));
-            g_ahThreads[i] = NIL_RTTHREAD;
-        }
-}
+    {
+        RTTEST_CHECK_RC(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
+        RTTEST_CHECK_RC(g_hTest, RTSemRWDestroy(g_ahSemRWs[i]), VINF_SUCCESS);
+    }
+    testWaitForThreads(10*1000, false);
+}
+
+
+static void test1(uint32_t cThreads, uint32_t cPasses)
+{
+    testIt(cThreads, cPasses, test1Thread, "critsect");
+}
+
+
+static void test2(uint32_t cThreads, uint32_t cPasses)
+{
+    testIt(cThreads, cPasses, test2Thread, "read-write");
+}
+
 
 static bool testIsLockValidationCompiledIn(void)
@@ -194,13 +364,39 @@
     RTLockValidatorSetEnabled(true);
     RTLockValidatorSetMayPanic(false);
+    RTLockValidatorSetQuiet(true);
     if (!testIsLockValidationCompiledIn())
         return RTTestErrorCount(g_hTest) > 0
             ? RTTestSummaryAndDestroy(g_hTest)
             : RTTestSkipAndDestroy(g_hTest, "deadlock detection is not compiled in");
-
-    test1(2);
-    test1(3);
-    test1(15);
-    test1(30);
+    RTLockValidatorSetQuiet(false);
+
+    /*
+     * Some initial tests with verbose output.
+     */
+    test1(3, 1);
+
+    test2(1, 1);
+    test2(3, 1);
+
+    /*
+     * More thorough testing without noisy output.
+     */
+    RTLockValidatorSetQuiet(true);
+
+    test1( 2, 1024);
+    test1( 3, 1024);
+    test1( 7,  896);
+    test1(10,  768);
+    test1(15,  512);
+    test1(30,  384);
+
+    test2( 1,  100);
+    test2( 2, 1024);
+    test2( 3, 1024);
+    test2( 7,  896);
+    test2(10,  768);
+    test2(15,  512);
+    test2(30,  384);
+
 
     return RTTestSummaryAndDestroy(g_hTest);
