Index: /trunk/include/iprt/lockvalidator.h
===================================================================
--- /trunk/include/iprt/lockvalidator.h	(revision 25699)
+++ /trunk/include/iprt/lockvalidator.h	(revision 25700)
@@ -35,4 +35,5 @@
 #include <iprt/assert.h>
 #include <iprt/thread.h>
+#include <iprt/stdarg.h>
 
 
@@ -737,4 +738,7 @@
  *                              order validation kicks in.  Minimum is 1 ms,
  *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   ...                 Format string arguments.
  *
  * @remarks The properties can be modified after creation by the
@@ -743,5 +747,35 @@
 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
-                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder);
+                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                         const char *pszNameFmt, ...);
+
+/**
+ * Creates a new lock validator class, all properties specified.
+ *
+ * @returns IPRT status code
+ * @param   phClass             Where to return the class handle.
+ * @param   pSrcPos             The source position of the create call.
+ * @param   fAutodidact         Whether the class should be allowed to teach
+ *                              itself new locking order rules (true), or if the
+ *                              user will teach it all it needs to know (false).
+ * @param   fRecursionOk        Whether to allow lock recursion or not.
+ * @param   fStrictReleaseOrder Enforce strict lock release order or not.
+ * @param   cMsMinDeadlock      Used to raise the sleep interval at which
+ *                              deadlock detection kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   cMsMinOrder         Used to raise the sleep interval at which lock
+ *                              order validation kicks in.  Minimum is 1 ms,
+ *                              while RT_INDEFINITE_WAIT will disable it.
+ * @param   pszNameFmt          Class name format string, optional (NULL).  Max
+ *                              length is 32 bytes.
+ * @param   va                  Format string arguments.
+ *
+ * @remarks The properties can be modified after creation by the
+ *          RTLockValidatorClassSet* methods.
+ */
+RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
+                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
+                                          RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                          const char *pszNameFmt, va_list va);
 
 /**
Index: /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25699)
+++ /trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp	(revision 25700)
@@ -47,4 +47,50 @@
 #include "internal/magics.h"
 #include "internal/thread.h"
+
+/*******************************************************************************
+*   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
+
+/** Hashes the class handle (pointer) into an apPriorLocksHash index. */
+#define RTLOCKVALCLASS_HASH(hClass) \
+    (   (uintptr_t)(hClass) \
+      % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
+         / sizeof(PRTLOCKVALCLASSREF)) )
+
+/** The max value for RTLOCKVALCLASSINT::cRefs. */
+#define RTLOCKVALCLASS_MAX_REFS                 UINT32_C(0xffff0000)
+/** The max value for RTLOCKVALCLASSREF::cLookups. */
+#define RTLOCKVALCLASSREF_MAX_LOOKUPS           UINT32_C(0xfffe0000)
+/** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will
+ *  be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */
+#define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX       UINT32_C(0xffff0000)
+
+
+/** @def RTLOCKVAL_WITH_RECURSION_RECORDS
+ *  Enable recursion records.  */
+#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+# define RTLOCKVAL_WITH_RECURSION_RECORDS  1
+#endif
+
+/** @def RTLOCKVAL_WITH_VERBOSE_DUMPS
+ * Enables some extra verbosity in the lock dumping.  */
+#if defined(DOXYGEN_RUNNING)
+# define RTLOCKVAL_WITH_VERBOSE_DUMPS
+#endif
+
+/** @def RTLOCKVAL_WITH_CLASS_HASH_STATS
+ * Enables collection prior class hash lookup statistics, dumping them when
+ * complaining about the class. */
+#if defined(DEBUG/*_bird*/) || defined(DOXYGEN_RUNNING)
+# define RTLOCKVAL_WITH_CLASS_HASH_STATS
+#endif
 
 
@@ -157,6 +203,5 @@
     /** Hash table containing frequently encountered prior locks. */
     PRTLOCKVALCLASSREF      apPriorLocksHash[11];
-#define RTLOCKVALCLASS_HASH_STATS
-#ifdef RTLOCKVALCLASS_HASH_STATS
+#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
     /** Hash hits. */
     uint32_t volatile       cHashHits;
@@ -170,47 +215,9 @@
      *           spawned it. */
     RTLOCKVALSRCPOS         CreatePos;
+    /** Class name. (Allocated after the end of the block as usual.) */
+    char const             *pszName;
 } RTLOCKVALCLASSINT;
 AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32);
 AssertCompileMemberOffset(RTLOCKVALCLASSINT, PriorLocks, 64);
-
-
-/*******************************************************************************
-*   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
-
-/** Hashes the class handle (pointer) into an apPriorLocksHash index. */
-#define RTLOCKVALCLASS_HASH(hClass) \
-    (   (uintptr_t)(hClass) \
-      % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
-         / sizeof(PRTLOCKVALCLASSREF)) )
-
-/** The max value for RTLOCKVALCLASSINT::cRefs. */
-#define RTLOCKVALCLASS_MAX_REFS                 UINT32_C(0xffff0000)
-/** The max value for RTLOCKVALCLASSREF::cLookups. */
-#define RTLOCKVALCLASSREF_MAX_LOOKUPS           UINT32_C(0xfffe0000)
-/** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will
- *  be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */
-#define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX       UINT32_C(0xffff0000)
-
-
-/** @def RTLOCKVAL_WITH_RECURSION_RECORDS
- *  Enable recursion records.  */
-#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
-# define RTLOCKVAL_WITH_RECURSION_RECORDS  1
-#endif
-
-/** @def RTLOCKVAL_WITH_VERBOSE_DUMPS
- * Enables some extra verbosity in the lock dumping.  */
-#if defined(DOXYGEN_RUNNING)
-# define RTLOCKVAL_WITH_VERBOSE_DUMPS
-#endif
 
 
@@ -382,8 +389,102 @@
 static void rtLockValComplainAboutClass(const char *pszPrefix, RTLOCKVALCLASSINT *pClass, uint32_t uSubClass, bool fVerbose)
 {
-    if (   VALID_PTR(pClass)
-        && pClass->u32Magic == RTLOCKVALCLASS_MAGIC)
-    {
-
+    if (ASMAtomicUoReadBool(&g_fLockValidatorQuiet))
+        return;
+
+    /* Stringify the sub-class. */
+    const char *pszSubClass;
+    char        szSubClass[32];
+    if (uSubClass < RTLOCKVAL_SUB_CLASS_USER)
+        switch (uSubClass)
+        {
+            case RTLOCKVAL_SUB_CLASS_NONE: pszSubClass = "none"; break;
+            case RTLOCKVAL_SUB_CLASS_ANY:  pszSubClass = "any"; break;
+            default:
+                RTStrPrintf(szSubClass, sizeof(szSubClass),  "invl-%u", uSubClass);
+                pszSubClass = szSubClass;
+                break;
+        }
+    else
+    {
+        RTStrPrintf(szSubClass, sizeof(szSubClass),  "%u", uSubClass);
+        pszSubClass = szSubClass;
+    }
+
+    /* Validate the class pointer. */
+    if (!VALID_PTR(pClass))
+    {
+        RTAssertMsg2AddWeak("%sbad class=%p sub-class=%s\n", pszPrefix, pClass, pszSubClass);
+        return;
+    }
+    if (pClass->u32Magic != RTLOCKVALCLASS_MAGIC)
+    {
+        RTAssertMsg2AddWeak("%sbad class=%p magic=%#x sub-class=%s\n", pszPrefix, pClass, pClass->u32Magic, pszSubClass);
+        return;
+    }
+
+    /* OK, dump the class info. */
+    RTAssertMsg2AddWeak("%sclass=%p %s created={%Rbn(%u) %Rfn %p} sub-class=%s\n", pszPrefix,
+                        pClass,
+                        pClass->pszName,
+                        pClass->CreatePos.pszFile,
+                        pClass->CreatePos.uLine,
+                        pClass->CreatePos.pszFunction,
+                        pClass->CreatePos.uId,
+                        pszSubClass);
+    if (fVerbose)
+    {
+        uint32_t i        = 0;
+        uint32_t cPrinted = 0;
+        for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext)
+            for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++, i++)
+            {
+                RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass;
+                if (pCurClass != NIL_RTLOCKVALCLASS)
+                {
+                    RTAssertMsg2AddWeak("%s%s #%02u: %s, %s, %u lookup%s\n", pszPrefix,
+                                        cPrinted == 0
+                                        ? "Prior:"
+                                        : "      ",
+                                        i,
+                                        pCurClass->pszName,
+                                        pChunk->aRefs[j].fAutodidacticism
+                                        ? "autodidactic"
+                                        : "manually    ",
+                                        pChunk->aRefs[j].cLookups,
+                                        pChunk->aRefs[j].cLookups != 1 ? "s" : "");
+                    cPrinted++;
+                }
+            }
+        if (!cPrinted)
+            RTAssertMsg2AddWeak("%sPrior: none\n", pszPrefix);
+#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
+        RTAssertMsg2AddWeak("%sHash Stats: %u hits, %u misses\n", pszPrefix, pClass->cHashHits, pClass->cHashMisses);
+#endif
+    }
+    else
+    {
+        uint32_t cPrinted = 0;
+        for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext)
+            for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++)
+            {
+                RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass;
+                if (pCurClass != NIL_RTLOCKVALCLASS)
+                {
+                    if ((cPrinted % 10) == 0)
+                        RTAssertMsg2AddWeak("%sPrior classes: %s%s", pszPrefix, pCurClass->pszName,
+                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
+                    else if ((cPrinted % 10) != 9)
+                        RTAssertMsg2AddWeak(", %s%s", pCurClass->pszName,
+                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
+                    else
+                        RTAssertMsg2AddWeak(", %s%s\n", pCurClass->pszName,
+                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
+                    cPrinted++;
+                }
+            }
+        if (!cPrinted)
+            RTAssertMsg2AddWeak("%sPrior classes: none\n", pszPrefix);
+        else if ((cPrinted % 10) != 0)
+            RTAssertMsg2AddWeak("\n");
     }
 }
@@ -562,6 +663,9 @@
  * @param   pThreadSelf         The calling thread.
  * @param   pRec                The main lock involved. Can be NULL.
- */
-static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec)
+ * @param   fDumpStack          Whether to dump the lock stack (true) or not
+ *                              (false).
+ */
+static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf,
+                                   PRTLOCKVALRECUNION pRec, bool fDumpStack)
 {
     if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet))
@@ -574,5 +678,6 @@
             RTAssertMsg2Weak("%s  [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>");
         rtLockValComplainAboutLock("Lock: ", pRec, "\n");
-        rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec);
+        if (fDumpStack)
+            rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec);
     }
 }
@@ -807,5 +912,5 @@
         rtLockValComplainFirst("Thread terminating owning locks!", NULL,
                                RT_FROM_MEMBER(pPerThread, RTTHREADINT, LockValidator),
-                               pPerThread->pStackTop);
+                               pPerThread->pStackTop, true);
         rtLockValComplainPanic();
     }
@@ -824,8 +929,22 @@
 }
 
-
 RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
-                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder)
+                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                         const char *pszNameFmt, ...)
+{
+    va_list va;
+    va_start(va, pszNameFmt);
+    int rc = RTLockValidatorClassCreateExV(phClass, pSrcPos, fAutodidact, fRecursionOk, fStrictReleaseOrder,
+                                           cMsMinDeadlock, cMsMinOrder, pszNameFmt, va);
+    va_end(va);
+    return rc;
+}
+
+
+RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
+                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
+                                          RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
+                                          const char *pszNameFmt, va_list va)
 {
     Assert(cMsMinDeadlock >= 1);
@@ -833,10 +952,31 @@
     AssertPtr(pSrcPos);
 
+    /*
+     * Format the name and calc its length.
+     */
+    size_t cbName;
+    char   szName[32];
+    if (pszNameFmt && *pszNameFmt)
+        cbName = RTStrPrintfV(szName, sizeof(szName), pszNameFmt, va) + 1;
+    else
+    {
+        static uint32_t volatile s_cAnonymous = 0;
+        uint32_t i = ASMAtomicIncU32(&s_cAnonymous);
+        cbName = RTStrPrintf(szName, sizeof(szName), "anon-%u", i - 1) + 1;
+    }
+
+    /*
+     * Figure out the file and function name lengths and allocate memory for
+     * it all.
+     */
     size_t const       cbFile   = pSrcPos->pszFile ? strlen(pSrcPos->pszFile) + 1 : 0;
     size_t const     cbFunction = pSrcPos->pszFile ? strlen(pSrcPos->pszFunction) + 1 : 0;
-    RTLOCKVALCLASSINT *pThis    = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction);
+    RTLOCKVALCLASSINT *pThis    = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction + cbName);
     if (!pThis)
         return VERR_NO_MEMORY;
 
+    /*
+     * Initialize the class data.
+     */
     pThis->Core.Key             = rtLockValidatorSrcPosHash(pSrcPos);
     pThis->Core.uchHeight       = 0;
@@ -871,5 +1011,7 @@
     pszDst += cbFile;
     pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL;
+    pszDst += cbFunction;
     Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key);
+    pThis->pszName              = (char *)memcpy(pszDst, szName, cbName);
 
     *phClass = pThis;
@@ -883,5 +1025,6 @@
     return RTLockValidatorClassCreateEx(phClass, &SrcPos,
                                         fAutodidact, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
-                                        1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
+                                        1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/,
+                                        NULL /*pszName*/);
 }
 
@@ -1003,5 +1146,6 @@
         int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos,
                                               true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
-                                              1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
+                                              1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/,
+                                              NULL /*pszName*/);
         if (RT_SUCCESS(rc))
         {
@@ -1069,5 +1213,5 @@
                     ASMAtomicWritePtr((void * volatile *)ppHashEntry, &pChunk->aRefs[i]);
 
-#ifdef RTLOCKVALCLASS_HASH_STATS
+#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
                 ASMAtomicIncU32(&pClass->cHashMisses);
 #endif
@@ -1099,5 +1243,5 @@
         if (RT_UNLIKELY(cLookups >= RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX))
             ASMAtomicWriteU32(&pRef->cLookups, RTLOCKVALCLASSREF_MAX_LOOKUPS);
-#ifdef RTLOCKVALCLASS_HASH_STATS
+#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
         ASMAtomicIncU32(&pClass->cHashHits);
 #endif
@@ -1581,5 +1725,5 @@
         {
             case RTLOCKVALRECEXCL_MAGIC:
-                Assert(pRec->Excl.cRecursion >= 1);
+                Assert(pCur->Excl.cRecursion >= 1);
                 pCur = pCur->Excl.pDown;
                 break;
@@ -1667,42 +1811,34 @@
     else
     {
-        /* Find the record above ours. */
-        PRTLOCKVALRECUNION pAbove = pThreadSelf->LockValidator.pStackTop;
-        while (pAbove)
-        {
-            switch (pAbove->Core.u32Magic)
+        /* Find the pointer to our record and unlink ourselves. */
+        PRTLOCKVALRECUNION pCur = pThreadSelf->LockValidator.pStackTop;
+        while (pCur)
+        {
+            PRTLOCKVALRECUNION volatile *ppDown;
+            switch (pCur->Core.u32Magic)
             {
                 case RTLOCKVALRECEXCL_MAGIC:
-                    Assert(pRec->Excl.cRecursion >= 1);
-                    if (pAbove->Excl.pDown == pRec)
-                    {
-                        rtLockValidatorWriteRecUnionPtr(&pAbove->Excl.pDown, pDown);
-                        return;
-                    }
-                    pAbove = pAbove->Excl.pDown;
+                    Assert(pCur->Excl.cRecursion >= 1);
+                    ppDown = &pCur->Excl.pDown;
                     break;
 
                 case RTLOCKVALRECSHRDOWN_MAGIC:
-                    Assert(pAbove->ShrdOwner.cRecursion >= 1);
-                    if (pAbove->ShrdOwner.pDown == pRec)
-                    {
-                        rtLockValidatorWriteRecUnionPtr(&pAbove->ShrdOwner.pDown, pDown);
-                        return;
-                    }
-                    pAbove = pAbove->ShrdOwner.pDown;
+                    Assert(pCur->ShrdOwner.cRecursion >= 1);
+                    ppDown = &pCur->ShrdOwner.pDown;
                     break;
 
                 case RTLOCKVALRECNEST_MAGIC:
-                    Assert(pAbove->Nest.cRecursion >= 1);
-                    if (pAbove->Nest.pDown == pRec)
-                    {
-                        rtLockValidatorWriteRecUnionPtr(&pAbove->Nest.pDown, pDown);
-                        return;
-                    }
-                    pAbove = pAbove->Nest.pDown;
+                    Assert(pCur->Nest.cRecursion >= 1);
+                    ppDown = &pCur->Nest.pDown;
                     break;
 
                 default:
-                    AssertMsgFailedReturnVoid(("%#x\n", pAbove->Core.u32Magic));
+                    AssertMsgFailedReturnVoid(("%#x\n", pCur->Core.u32Magic));
+            }
+            pCur = *ppDown;
+            if (pCur == pRec)
+            {
+                rtLockValidatorWriteRecUnionPtr(ppDown, pDown);
+                return;
             }
         }
@@ -1810,47 +1946,31 @@
     {
         /* Find the record above ours. */
-        PRTLOCKVALRECUNION pAbove = NULL;
-        while (pNest)
-        {
+        PRTLOCKVALRECUNION volatile *ppDown = NULL;
+        for (;;)
+        {
+            AssertMsgReturnVoid(pNest, ("%p %p\n", pRec, pThreadSelf));
             switch (pNest->Core.u32Magic)
             {
                 case RTLOCKVALRECEXCL_MAGIC:
-                    pAbove  = pNest;
-                    pNest   = pNest->Excl.pDown;
-                    break;
+                    ppDown = &pNest->Excl.pDown;
+                    pNest = *ppDown;
+                    continue;
                 case RTLOCKVALRECSHRDOWN_MAGIC:
-                    pAbove  = pNest;
-                    pNest   = pNest->ShrdOwner.pDown;
-                    break;
+                    ppDown = &pNest->ShrdOwner.pDown;
+                    pNest = *ppDown;
+                    continue;
                 case RTLOCKVALRECNEST_MAGIC:
                     if (pNest->Nest.pRec == pRec)
-                    {
-                        pNest = pNest;
                         break;
-                    }
-                    pAbove  = pNest;
-                    pNest   = pNest->Nest.pDown;
-                    break;
+                    ppDown = &pNest->Nest.pDown;
+                    pNest = *ppDown;
+                    continue;
                 default:
                     AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic));
             }
-        }
-        AssertMsg(pNest, ("%p %p\n", pRec, pThreadSelf));
-        AssertMsg(pAbove, ("%p %p\n", pRec, pThreadSelf));
+            break; /* ugly */
+        }
         Assert(pNest->Nest.cRecursion == cRecursion + 1);
-        switch (pAbove->Core.u32Magic)
-        {
-            case RTLOCKVALRECEXCL_MAGIC:
-                rtLockValidatorWriteRecUnionPtr(&pNest->Excl.pDown, pNest->Nest.pDown);
-                break;
-            case RTLOCKVALRECSHRDOWN_MAGIC:
-                rtLockValidatorWriteRecUnionPtr(&pNest->ShrdOwner.pDown, pNest->Nest.pDown);
-                break;
-            case RTLOCKVALRECNEST_MAGIC:
-                rtLockValidatorWriteRecUnionPtr(&pNest->Nest.pDown, pNest->Nest.pDown);
-                break;
-            default:
-                AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic));
-        }
+        rtLockValidatorWriteRecUnionPtr(ppDown, pNest->Nest.pDown);
     }
 
@@ -1878,9 +1998,10 @@
 
 {
-    rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1);
+    rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1, false);
     rtLockValComplainAboutLock("Other lock:   ", pRec2, "\n");
     rtLockValComplainAboutClass("My class:    ", pClass1, rtLockValidatorRecGetSubClass(pRec1), true /*fVerbose*/);
     rtLockValComplainAboutClass("Other class: ", pClass2, rtLockValidatorRecGetSubClass(pRec2), true /*fVerbose*/);
     rtLockValComplainAboutLockStack(pThreadSelf, 0, 0, pRec2);
+    rtLockValComplainPanic();
     return VERR_SEM_LV_WRONG_ORDER;
 }
@@ -1972,24 +2093,26 @@
         AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR);
 
-        uint32_t            uPriorSubClass;
-        PRTLOCKVALRECUNION  pDown;
-        RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
-        if (pPriorClass != NIL_RTLOCKVALCLASS)
-        {
-            AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
-            AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
-            if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
+        if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
+            pCur = pCur->Nest.pDown;
+        else
+        {
+            PRTLOCKVALRECUNION  pDown;
+            uint32_t            uPriorSubClass;
+            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
+            if (pPriorClass != NIL_RTLOCKVALCLASS)
             {
-                if (   pClass == pPriorClass
-                    || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
-                    return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
-                                                          pRec, pCur, pClass, pPriorClass);
-                cNewRules++;
+                AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
+                AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
+                if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
+                {
+                    if (   pClass == pPriorClass
+                        || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
+                        return rtLockValidatorStackWrongOrder("Wrong locking order! (more than one)", pSrcPos, pThreadSelf,
+                                                              pRec, pCur, pClass, pPriorClass);
+                    cNewRules++;
+                }
             }
-        }
-
-        pCur = pDown;
-        if (!pCur)
-            return VINF_SUCCESS;
+            pCur = pDown;
+        }
     }
 
@@ -2019,52 +2142,60 @@
 
         /* Check */
-        pCur = pFirstBadDown;
+        pCur = pFirstBadRec;
         while (pCur)
         {
-            uint32_t            uPriorSubClass;
-            PRTLOCKVALRECUNION  pDown;
-            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
-            if (pPriorClass != NIL_RTLOCKVALCLASS)
+            if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
+                pCur = pCur->Nest.pDown;
+            else
             {
-                if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
+                uint32_t            uPriorSubClass;
+                PRTLOCKVALRECUNION  pDown;
+                RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
+                if (pPriorClass != NIL_RTLOCKVALCLASS)
                 {
-                    if (   pClass == pPriorClass
-                        || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
+                    if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
                     {
-                        if (RT_SUCCESS(rcLock))
-                            RTCritSectLeave(&g_LockValClassTeachCS);
-                        return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
-                                                              pRec, pCur, pClass, pPriorClass);
+                        if (   pClass == pPriorClass
+                            || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
+                        {
+                            if (RT_SUCCESS(rcLock))
+                                RTCritSectLeave(&g_LockValClassTeachCS);
+                            return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
+                                                                  pRec, pCur, pClass, pPriorClass);
+                        }
                     }
                 }
+                pCur = pDown;
             }
-
-            pCur = pDown;
         }
 
         /* Iterate the stack yet again, adding new rules this time. */
-        pCur = pFirstBadDown;
+        pCur = pFirstBadRec;
         while (pCur)
         {
-            uint32_t            uPriorSubClass;
-            PRTLOCKVALRECUNION  pDown;
-            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
-            if (pPriorClass != NIL_RTLOCKVALCLASS)
+            if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
+                pCur = pCur->Nest.pDown;
+            else
             {
-                if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
+                uint32_t            uPriorSubClass;
+                PRTLOCKVALRECUNION  pDown;
+                RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
+                if (pPriorClass != NIL_RTLOCKVALCLASS)
                 {
-                    Assert(   pClass != pPriorClass
-                           && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
-                    int rc = rtLockValidatorClassAddPriorClass(pClass, pFirstBadClass, true /*fAutodidacticism*/, pSrcPos);
-                    if (RT_FAILURE(rc))
+                    if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
                     {
-                        Assert(rc == VERR_NO_MEMORY);
-                        break;
+                        Assert(   pClass != pPriorClass
+                               && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
+                        int rc = rtLockValidatorClassAddPriorClass(pClass, pPriorClass, true /*fAutodidacticism*/, pSrcPos);
+                        if (RT_FAILURE(rc))
+                        {
+                            Assert(rc == VERR_NO_MEMORY);
+                            break;
+                        }
+                        Assert(rtLockValidatorClassIsPriorClass(pClass, pPriorClass));
                     }
-                    Assert(rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
                 }
+                pCur = pDown;
             }
-
-            pCur = pDown;
         }
 
@@ -2113,17 +2244,21 @@
         AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR);
 
-        uint32_t            uPriorSubClass;
-        PRTLOCKVALRECUNION  pDown;
-        RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
-        if (pPriorClass != NIL_RTLOCKVALCLASS)
-        {
-            AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
-            AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
-            if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)))
-                return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos,
-                                                              pPriorClass, pCur, pDown);
-        }
-
-        pCur = pDown;
+        if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
+            pCur = pCur->Nest.pDown;
+        else
+        {
+            uint32_t            uPriorSubClass;
+            PRTLOCKVALRECUNION  pDown;
+            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
+            if (pPriorClass != NIL_RTLOCKVALCLASS)
+            {
+                AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
+                AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
+                if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)))
+                    return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos,
+                                                                  pPriorClass, pCur, pDown);
+            }
+            pCur = pDown;
+        }
         if (!pCur)
             return VINF_SUCCESS;
@@ -2153,5 +2288,5 @@
         return VINF_SUCCESS;
 
-    rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec);
+    rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec, true);
     rtLockValComplainPanic();
     return VERR_SEM_LV_WRONG_ORDER;
@@ -2554,5 +2689,5 @@
             default:            AssertFailed(); pszWhat = "!unexpected rc!"; break;
         }
-        rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL);
+        rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL, true);
         rtLockValComplainMore("---- start of deadlock chain - %u entries ----\n", pStack->c);
         for (uint32_t i = 0; i < pStack->c; i++)
@@ -2805,5 +2940,5 @@
     {
         rtLockValComplainFirst("Recursion not allowed by the class!",
-                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec);
+                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true);
         rtLockValComplainPanic();
         return VERR_SEM_LV_NESTED;
@@ -2849,5 +2984,5 @@
     {
         rtLockValComplainFirst("Mixed recursion not allowed by the class!",
-                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec);
+                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true);
         rtLockValComplainPanic();
         return VERR_SEM_LV_NESTED;
@@ -2955,5 +3090,5 @@
                 && !pRecU->Excl.hClass->fRecursionOk))
         {
-            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU);
+            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true);
             rtLockValComplainPanic();
             rc = VERR_SEM_LV_NESTED;
@@ -3172,5 +3307,5 @@
             )
         {
-            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU);
+            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true);
             rtLockValComplainPanic();
             rc =  VERR_SEM_LV_NESTED;
@@ -3612,5 +3747,5 @@
     if (RT_UNLIKELY(!pEntry))
     {
-        rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);
+        rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true);
         rtLockValComplainPanic();
         return VERR_SEM_LV_NOT_OWNER;
@@ -3667,5 +3802,5 @@
     if (RT_UNLIKELY(!pEntry))
     {
-        rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);
+        rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true);
         rtLockValComplainPanic();
         return VERR_SEM_LV_NOT_SIGNALLER;
