VirtualBox

Changeset 25700 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jan 9, 2010 9:34:21 PM (15 years ago)
Author:
vboxsync
Message:

iprt/lockvalidator: finishing the code and fixing bugs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp

    r25694 r25700  
    4747#include "internal/magics.h"
    4848#include "internal/thread.h"
     49
     50/*******************************************************************************
     51*   Defined Constants And Macros                                               *
     52*******************************************************************************/
     53/** Macro that asserts that a pointer is aligned correctly.
     54 * Only used when fighting bugs. */
     55#if 1
     56# define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \
     57    AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));
     58#else
     59# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   do { } while (0)
     60#endif
     61
     62/** Hashes the class handle (pointer) into an apPriorLocksHash index. */
     63#define RTLOCKVALCLASS_HASH(hClass) \
     64    (   (uintptr_t)(hClass) \
     65      % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
     66         / sizeof(PRTLOCKVALCLASSREF)) )
     67
     68/** The max value for RTLOCKVALCLASSINT::cRefs. */
     69#define RTLOCKVALCLASS_MAX_REFS                 UINT32_C(0xffff0000)
     70/** The max value for RTLOCKVALCLASSREF::cLookups. */
     71#define RTLOCKVALCLASSREF_MAX_LOOKUPS           UINT32_C(0xfffe0000)
     72/** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will
     73 *  be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */
     74#define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX       UINT32_C(0xffff0000)
     75
     76
     77/** @def RTLOCKVAL_WITH_RECURSION_RECORDS
     78 *  Enable recursion records.  */
     79#if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
     80# define RTLOCKVAL_WITH_RECURSION_RECORDS  1
     81#endif
     82
     83/** @def RTLOCKVAL_WITH_VERBOSE_DUMPS
     84 * Enables some extra verbosity in the lock dumping.  */
     85#if defined(DOXYGEN_RUNNING)
     86# define RTLOCKVAL_WITH_VERBOSE_DUMPS
     87#endif
     88
     89/** @def RTLOCKVAL_WITH_CLASS_HASH_STATS
     90 * Enables collection prior class hash lookup statistics, dumping them when
     91 * complaining about the class. */
     92#if defined(DEBUG/*_bird*/) || defined(DOXYGEN_RUNNING)
     93# define RTLOCKVAL_WITH_CLASS_HASH_STATS
     94#endif
    4995
    5096
     
    157203    /** Hash table containing frequently encountered prior locks. */
    158204    PRTLOCKVALCLASSREF      apPriorLocksHash[11];
    159 #define RTLOCKVALCLASS_HASH_STATS
    160 #ifdef RTLOCKVALCLASS_HASH_STATS
     205#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
    161206    /** Hash hits. */
    162207    uint32_t volatile       cHashHits;
     
    170215     *           spawned it. */
    171216    RTLOCKVALSRCPOS         CreatePos;
     217    /** Class name. (Allocated after the end of the block as usual.) */
     218    char const             *pszName;
    172219} RTLOCKVALCLASSINT;
    173220AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32);
    174221AssertCompileMemberOffset(RTLOCKVALCLASSINT, PriorLocks, 64);
    175 
    176 
    177 /*******************************************************************************
    178 *   Defined Constants And Macros                                               *
    179 *******************************************************************************/
    180 /** Macro that asserts that a pointer is aligned correctly.
    181  * Only used when fighting bugs. */
    182 #if 1
    183 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \
    184     AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));
    185 #else
    186 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   do { } while (0)
    187 #endif
    188 
    189 /** Hashes the class handle (pointer) into an apPriorLocksHash index. */
    190 #define RTLOCKVALCLASS_HASH(hClass) \
    191     (   (uintptr_t)(hClass) \
    192       % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
    193          / sizeof(PRTLOCKVALCLASSREF)) )
    194 
    195 /** The max value for RTLOCKVALCLASSINT::cRefs. */
    196 #define RTLOCKVALCLASS_MAX_REFS                 UINT32_C(0xffff0000)
    197 /** The max value for RTLOCKVALCLASSREF::cLookups. */
    198 #define RTLOCKVALCLASSREF_MAX_LOOKUPS           UINT32_C(0xfffe0000)
    199 /** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will
    200  *  be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */
    201 #define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX       UINT32_C(0xffff0000)
    202 
    203 
    204 /** @def RTLOCKVAL_WITH_RECURSION_RECORDS
    205  *  Enable recursion records.  */
    206 #if defined(IN_RING3) || defined(DOXYGEN_RUNNING)
    207 # define RTLOCKVAL_WITH_RECURSION_RECORDS  1
    208 #endif
    209 
    210 /** @def RTLOCKVAL_WITH_VERBOSE_DUMPS
    211  * Enables some extra verbosity in the lock dumping.  */
    212 #if defined(DOXYGEN_RUNNING)
    213 # define RTLOCKVAL_WITH_VERBOSE_DUMPS
    214 #endif
    215222
    216223
     
    382389static void rtLockValComplainAboutClass(const char *pszPrefix, RTLOCKVALCLASSINT *pClass, uint32_t uSubClass, bool fVerbose)
    383390{
    384     if (   VALID_PTR(pClass)
    385         && pClass->u32Magic == RTLOCKVALCLASS_MAGIC)
    386     {
    387 
     391    if (ASMAtomicUoReadBool(&g_fLockValidatorQuiet))
     392        return;
     393
     394    /* Stringify the sub-class. */
     395    const char *pszSubClass;
     396    char        szSubClass[32];
     397    if (uSubClass < RTLOCKVAL_SUB_CLASS_USER)
     398        switch (uSubClass)
     399        {
     400            case RTLOCKVAL_SUB_CLASS_NONE: pszSubClass = "none"; break;
     401            case RTLOCKVAL_SUB_CLASS_ANY:  pszSubClass = "any"; break;
     402            default:
     403                RTStrPrintf(szSubClass, sizeof(szSubClass),  "invl-%u", uSubClass);
     404                pszSubClass = szSubClass;
     405                break;
     406        }
     407    else
     408    {
     409        RTStrPrintf(szSubClass, sizeof(szSubClass),  "%u", uSubClass);
     410        pszSubClass = szSubClass;
     411    }
     412
     413    /* Validate the class pointer. */
     414    if (!VALID_PTR(pClass))
     415    {
     416        RTAssertMsg2AddWeak("%sbad class=%p sub-class=%s\n", pszPrefix, pClass, pszSubClass);
     417        return;
     418    }
     419    if (pClass->u32Magic != RTLOCKVALCLASS_MAGIC)
     420    {
     421        RTAssertMsg2AddWeak("%sbad class=%p magic=%#x sub-class=%s\n", pszPrefix, pClass, pClass->u32Magic, pszSubClass);
     422        return;
     423    }
     424
     425    /* OK, dump the class info. */
     426    RTAssertMsg2AddWeak("%sclass=%p %s created={%Rbn(%u) %Rfn %p} sub-class=%s\n", pszPrefix,
     427                        pClass,
     428                        pClass->pszName,
     429                        pClass->CreatePos.pszFile,
     430                        pClass->CreatePos.uLine,
     431                        pClass->CreatePos.pszFunction,
     432                        pClass->CreatePos.uId,
     433                        pszSubClass);
     434    if (fVerbose)
     435    {
     436        uint32_t i        = 0;
     437        uint32_t cPrinted = 0;
     438        for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext)
     439            for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++, i++)
     440            {
     441                RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass;
     442                if (pCurClass != NIL_RTLOCKVALCLASS)
     443                {
     444                    RTAssertMsg2AddWeak("%s%s #%02u: %s, %s, %u lookup%s\n", pszPrefix,
     445                                        cPrinted == 0
     446                                        ? "Prior:"
     447                                        : "      ",
     448                                        i,
     449                                        pCurClass->pszName,
     450                                        pChunk->aRefs[j].fAutodidacticism
     451                                        ? "autodidactic"
     452                                        : "manually    ",
     453                                        pChunk->aRefs[j].cLookups,
     454                                        pChunk->aRefs[j].cLookups != 1 ? "s" : "");
     455                    cPrinted++;
     456                }
     457            }
     458        if (!cPrinted)
     459            RTAssertMsg2AddWeak("%sPrior: none\n", pszPrefix);
     460#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
     461        RTAssertMsg2AddWeak("%sHash Stats: %u hits, %u misses\n", pszPrefix, pClass->cHashHits, pClass->cHashMisses);
     462#endif
     463    }
     464    else
     465    {
     466        uint32_t cPrinted = 0;
     467        for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext)
     468            for (unsigned j = 0; j < RT_ELEMENTS(pChunk->aRefs); j++)
     469            {
     470                RTLOCKVALCLASSINT *pCurClass = pChunk->aRefs[j].hClass;
     471                if (pCurClass != NIL_RTLOCKVALCLASS)
     472                {
     473                    if ((cPrinted % 10) == 0)
     474                        RTAssertMsg2AddWeak("%sPrior classes: %s%s", pszPrefix, pCurClass->pszName,
     475                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
     476                    else if ((cPrinted % 10) != 9)
     477                        RTAssertMsg2AddWeak(", %s%s", pCurClass->pszName,
     478                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
     479                    else
     480                        RTAssertMsg2AddWeak(", %s%s\n", pCurClass->pszName,
     481                                            pChunk->aRefs[j].fAutodidacticism ? "*" : "");
     482                    cPrinted++;
     483                }
     484            }
     485        if (!cPrinted)
     486            RTAssertMsg2AddWeak("%sPrior classes: none\n", pszPrefix);
     487        else if ((cPrinted % 10) != 0)
     488            RTAssertMsg2AddWeak("\n");
    388489    }
    389490}
     
    562663 * @param   pThreadSelf         The calling thread.
    563664 * @param   pRec                The main lock involved. Can be NULL.
    564  */
    565 static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf, PRTLOCKVALRECUNION pRec)
     665 * @param   fDumpStack          Whether to dump the lock stack (true) or not
     666 *                              (false).
     667 */
     668static void rtLockValComplainFirst(const char *pszWhat, PCRTLOCKVALSRCPOS pSrcPos, PRTTHREADINT pThreadSelf,
     669                                   PRTLOCKVALRECUNION pRec, bool fDumpStack)
    566670{
    567671    if (!ASMAtomicUoReadBool(&g_fLockValidatorQuiet))
     
    574678            RTAssertMsg2Weak("%s  [thrd=%s]\n", pszWhat, VALID_PTR(pThreadSelf) ? pThreadSelf->szName : "<NIL>");
    575679        rtLockValComplainAboutLock("Lock: ", pRec, "\n");
    576         rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec);
     680        if (fDumpStack)
     681            rtLockValComplainAboutLockStack(pThreadSelf, 0, 1, pRec);
    577682    }
    578683}
     
    807912        rtLockValComplainFirst("Thread terminating owning locks!", NULL,
    808913                               RT_FROM_MEMBER(pPerThread, RTTHREADINT, LockValidator),
    809                                pPerThread->pStackTop);
     914                               pPerThread->pStackTop, true);
    810915        rtLockValComplainPanic();
    811916    }
     
    824929}
    825930
    826 
    827931RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
    828932                                         bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
    829                                          RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder)
     933                                         RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
     934                                         const char *pszNameFmt, ...)
     935{
     936    va_list va;
     937    va_start(va, pszNameFmt);
     938    int rc = RTLockValidatorClassCreateExV(phClass, pSrcPos, fAutodidact, fRecursionOk, fStrictReleaseOrder,
     939                                           cMsMinDeadlock, cMsMinOrder, pszNameFmt, va);
     940    va_end(va);
     941    return rc;
     942}
     943
     944
     945RTDECL(int) RTLockValidatorClassCreateExV(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
     946                                          bool fAutodidact, bool fRecursionOk, bool fStrictReleaseOrder,
     947                                          RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder,
     948                                          const char *pszNameFmt, va_list va)
    830949{
    831950    Assert(cMsMinDeadlock >= 1);
     
    833952    AssertPtr(pSrcPos);
    834953
     954    /*
     955     * Format the name and calc its length.
     956     */
     957    size_t cbName;
     958    char   szName[32];
     959    if (pszNameFmt && *pszNameFmt)
     960        cbName = RTStrPrintfV(szName, sizeof(szName), pszNameFmt, va) + 1;
     961    else
     962    {
     963        static uint32_t volatile s_cAnonymous = 0;
     964        uint32_t i = ASMAtomicIncU32(&s_cAnonymous);
     965        cbName = RTStrPrintf(szName, sizeof(szName), "anon-%u", i - 1) + 1;
     966    }
     967
     968    /*
     969     * Figure out the file and function name lengths and allocate memory for
     970     * it all.
     971     */
    835972    size_t const       cbFile   = pSrcPos->pszFile ? strlen(pSrcPos->pszFile) + 1 : 0;
    836973    size_t const     cbFunction = pSrcPos->pszFile ? strlen(pSrcPos->pszFunction) + 1 : 0;
    837     RTLOCKVALCLASSINT *pThis    = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction);
     974    RTLOCKVALCLASSINT *pThis    = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction + cbName);
    838975    if (!pThis)
    839976        return VERR_NO_MEMORY;
    840977
     978    /*
     979     * Initialize the class data.
     980     */
    841981    pThis->Core.Key             = rtLockValidatorSrcPosHash(pSrcPos);
    842982    pThis->Core.uchHeight       = 0;
     
    8711011    pszDst += cbFile;
    8721012    pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL;
     1013    pszDst += cbFunction;
    8731014    Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key);
     1015    pThis->pszName              = (char *)memcpy(pszDst, szName, cbName);
    8741016
    8751017    *phClass = pThis;
     
    8831025    return RTLockValidatorClassCreateEx(phClass, &SrcPos,
    8841026                                        fAutodidact, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
    885                                         1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
     1027                                        1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/,
     1028                                        NULL /*pszName*/);
    8861029}
    8871030
     
    10031146        int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos,
    10041147                                              true /*fAutodidact*/, true /*fRecursionOk*/, false /*fStrictReleaseOrder*/,
    1005                                               1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
     1148                                              1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/,
     1149                                              NULL /*pszName*/);
    10061150        if (RT_SUCCESS(rc))
    10071151        {
     
    10691213                    ASMAtomicWritePtr((void * volatile *)ppHashEntry, &pChunk->aRefs[i]);
    10701214
    1071 #ifdef RTLOCKVALCLASS_HASH_STATS
     1215#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
    10721216                ASMAtomicIncU32(&pClass->cHashMisses);
    10731217#endif
     
    10991243        if (RT_UNLIKELY(cLookups >= RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX))
    11001244            ASMAtomicWriteU32(&pRef->cLookups, RTLOCKVALCLASSREF_MAX_LOOKUPS);
    1101 #ifdef RTLOCKVALCLASS_HASH_STATS
     1245#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
    11021246        ASMAtomicIncU32(&pClass->cHashHits);
    11031247#endif
     
    15811725        {
    15821726            case RTLOCKVALRECEXCL_MAGIC:
    1583                 Assert(pRec->Excl.cRecursion >= 1);
     1727                Assert(pCur->Excl.cRecursion >= 1);
    15841728                pCur = pCur->Excl.pDown;
    15851729                break;
     
    16671811    else
    16681812    {
    1669         /* Find the record above ours. */
    1670         PRTLOCKVALRECUNION pAbove = pThreadSelf->LockValidator.pStackTop;
    1671         while (pAbove)
    1672         {
    1673             switch (pAbove->Core.u32Magic)
     1813        /* Find the pointer to our record and unlink ourselves. */
     1814        PRTLOCKVALRECUNION pCur = pThreadSelf->LockValidator.pStackTop;
     1815        while (pCur)
     1816        {
     1817            PRTLOCKVALRECUNION volatile *ppDown;
     1818            switch (pCur->Core.u32Magic)
    16741819            {
    16751820                case RTLOCKVALRECEXCL_MAGIC:
    1676                     Assert(pRec->Excl.cRecursion >= 1);
    1677                     if (pAbove->Excl.pDown == pRec)
    1678                     {
    1679                         rtLockValidatorWriteRecUnionPtr(&pAbove->Excl.pDown, pDown);
    1680                         return;
    1681                     }
    1682                     pAbove = pAbove->Excl.pDown;
     1821                    Assert(pCur->Excl.cRecursion >= 1);
     1822                    ppDown = &pCur->Excl.pDown;
    16831823                    break;
    16841824
    16851825                case RTLOCKVALRECSHRDOWN_MAGIC:
    1686                     Assert(pAbove->ShrdOwner.cRecursion >= 1);
    1687                     if (pAbove->ShrdOwner.pDown == pRec)
    1688                     {
    1689                         rtLockValidatorWriteRecUnionPtr(&pAbove->ShrdOwner.pDown, pDown);
    1690                         return;
    1691                     }
    1692                     pAbove = pAbove->ShrdOwner.pDown;
     1826                    Assert(pCur->ShrdOwner.cRecursion >= 1);
     1827                    ppDown = &pCur->ShrdOwner.pDown;
    16931828                    break;
    16941829
    16951830                case RTLOCKVALRECNEST_MAGIC:
    1696                     Assert(pAbove->Nest.cRecursion >= 1);
    1697                     if (pAbove->Nest.pDown == pRec)
    1698                     {
    1699                         rtLockValidatorWriteRecUnionPtr(&pAbove->Nest.pDown, pDown);
    1700                         return;
    1701                     }
    1702                     pAbove = pAbove->Nest.pDown;
     1831                    Assert(pCur->Nest.cRecursion >= 1);
     1832                    ppDown = &pCur->Nest.pDown;
    17031833                    break;
    17041834
    17051835                default:
    1706                     AssertMsgFailedReturnVoid(("%#x\n", pAbove->Core.u32Magic));
     1836                    AssertMsgFailedReturnVoid(("%#x\n", pCur->Core.u32Magic));
     1837            }
     1838            pCur = *ppDown;
     1839            if (pCur == pRec)
     1840            {
     1841                rtLockValidatorWriteRecUnionPtr(ppDown, pDown);
     1842                return;
    17071843            }
    17081844        }
     
    18101946    {
    18111947        /* Find the record above ours. */
    1812         PRTLOCKVALRECUNION pAbove = NULL;
    1813         while (pNest)
    1814         {
     1948        PRTLOCKVALRECUNION volatile *ppDown = NULL;
     1949        for (;;)
     1950        {
     1951            AssertMsgReturnVoid(pNest, ("%p %p\n", pRec, pThreadSelf));
    18151952            switch (pNest->Core.u32Magic)
    18161953            {
    18171954                case RTLOCKVALRECEXCL_MAGIC:
    1818                     pAbove  = pNest;
    1819                     pNest   = pNest->Excl.pDown;
    1820                     break;
     1955                    ppDown = &pNest->Excl.pDown;
     1956                    pNest = *ppDown;
     1957                    continue;
    18211958                case RTLOCKVALRECSHRDOWN_MAGIC:
    1822                     pAbove  = pNest;
    1823                     pNest   = pNest->ShrdOwner.pDown;
    1824                     break;
     1959                    ppDown = &pNest->ShrdOwner.pDown;
     1960                    pNest = *ppDown;
     1961                    continue;
    18251962                case RTLOCKVALRECNEST_MAGIC:
    18261963                    if (pNest->Nest.pRec == pRec)
    1827                     {
    1828                         pNest = pNest;
    18291964                        break;
    1830                     }
    1831                     pAbove  = pNest;
    1832                     pNest   = pNest->Nest.pDown;
    1833                     break;
     1965                    ppDown = &pNest->Nest.pDown;
     1966                    pNest = *ppDown;
     1967                    continue;
    18341968                default:
    18351969                    AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic));
    18361970            }
    1837         }
    1838         AssertMsg(pNest, ("%p %p\n", pRec, pThreadSelf));
    1839         AssertMsg(pAbove, ("%p %p\n", pRec, pThreadSelf));
     1971            break; /* ugly */
     1972        }
    18401973        Assert(pNest->Nest.cRecursion == cRecursion + 1);
    1841         switch (pAbove->Core.u32Magic)
    1842         {
    1843             case RTLOCKVALRECEXCL_MAGIC:
    1844                 rtLockValidatorWriteRecUnionPtr(&pNest->Excl.pDown, pNest->Nest.pDown);
    1845                 break;
    1846             case RTLOCKVALRECSHRDOWN_MAGIC:
    1847                 rtLockValidatorWriteRecUnionPtr(&pNest->ShrdOwner.pDown, pNest->Nest.pDown);
    1848                 break;
    1849             case RTLOCKVALRECNEST_MAGIC:
    1850                 rtLockValidatorWriteRecUnionPtr(&pNest->Nest.pDown, pNest->Nest.pDown);
    1851                 break;
    1852             default:
    1853                 AssertMsgFailedReturnVoid(("%#x\n", pNest->Core.u32Magic));
    1854         }
     1974        rtLockValidatorWriteRecUnionPtr(ppDown, pNest->Nest.pDown);
    18551975    }
    18561976
     
    18781998
    18791999{
    1880     rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1);
     2000    rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pRec1, false);
    18812001    rtLockValComplainAboutLock("Other lock:   ", pRec2, "\n");
    18822002    rtLockValComplainAboutClass("My class:    ", pClass1, rtLockValidatorRecGetSubClass(pRec1), true /*fVerbose*/);
    18832003    rtLockValComplainAboutClass("Other class: ", pClass2, rtLockValidatorRecGetSubClass(pRec2), true /*fVerbose*/);
    18842004    rtLockValComplainAboutLockStack(pThreadSelf, 0, 0, pRec2);
     2005    rtLockValComplainPanic();
    18852006    return VERR_SEM_LV_WRONG_ORDER;
    18862007}
     
    19722093        AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR);
    19732094
    1974         uint32_t            uPriorSubClass;
    1975         PRTLOCKVALRECUNION  pDown;
    1976         RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
    1977         if (pPriorClass != NIL_RTLOCKVALCLASS)
    1978         {
    1979             AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
    1980             AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
    1981             if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
     2095        if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
     2096            pCur = pCur->Nest.pDown;
     2097        else
     2098        {
     2099            PRTLOCKVALRECUNION  pDown;
     2100            uint32_t            uPriorSubClass;
     2101            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
     2102            if (pPriorClass != NIL_RTLOCKVALCLASS)
    19822103            {
    1983                 if (   pClass == pPriorClass
    1984                     || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
    1985                     return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
    1986                                                           pRec, pCur, pClass, pPriorClass);
    1987                 cNewRules++;
     2104                AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
     2105                AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
     2106                if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
     2107                {
     2108                    if (   pClass == pPriorClass
     2109                        || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
     2110                        return rtLockValidatorStackWrongOrder("Wrong locking order! (more than one)", pSrcPos, pThreadSelf,
     2111                                                              pRec, pCur, pClass, pPriorClass);
     2112                    cNewRules++;
     2113                }
    19882114            }
    1989         }
    1990 
    1991         pCur = pDown;
    1992         if (!pCur)
    1993             return VINF_SUCCESS;
     2115            pCur = pDown;
     2116        }
    19942117    }
    19952118
     
    20192142
    20202143        /* Check */
    2021         pCur = pFirstBadDown;
     2144        pCur = pFirstBadRec;
    20222145        while (pCur)
    20232146        {
    2024             uint32_t            uPriorSubClass;
    2025             PRTLOCKVALRECUNION  pDown;
    2026             RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
    2027             if (pPriorClass != NIL_RTLOCKVALCLASS)
     2147            if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
     2148                pCur = pCur->Nest.pDown;
     2149            else
    20282150            {
    2029                 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
     2151                uint32_t            uPriorSubClass;
     2152                PRTLOCKVALRECUNION  pDown;
     2153                RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
     2154                if (pPriorClass != NIL_RTLOCKVALCLASS)
    20302155                {
    2031                     if (   pClass == pPriorClass
    2032                         || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
     2156                    if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
    20332157                    {
    2034                         if (RT_SUCCESS(rcLock))
    2035                             RTCritSectLeave(&g_LockValClassTeachCS);
    2036                         return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
    2037                                                               pRec, pCur, pClass, pPriorClass);
     2158                        if (   pClass == pPriorClass
     2159                            || rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
     2160                        {
     2161                            if (RT_SUCCESS(rcLock))
     2162                                RTCritSectLeave(&g_LockValClassTeachCS);
     2163                            return rtLockValidatorStackWrongOrder("Wrong locking order! (2nd)", pSrcPos, pThreadSelf,
     2164                                                                  pRec, pCur, pClass, pPriorClass);
     2165                        }
    20382166                    }
    20392167                }
     2168                pCur = pDown;
    20402169            }
    2041 
    2042             pCur = pDown;
    20432170        }
    20442171
    20452172        /* Iterate the stack yet again, adding new rules this time. */
    2046         pCur = pFirstBadDown;
     2173        pCur = pFirstBadRec;
    20472174        while (pCur)
    20482175        {
    2049             uint32_t            uPriorSubClass;
    2050             PRTLOCKVALRECUNION  pDown;
    2051             RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
    2052             if (pPriorClass != NIL_RTLOCKVALCLASS)
     2176            if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
     2177                pCur = pCur->Nest.pDown;
     2178            else
    20532179            {
    2054                 if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
     2180                uint32_t            uPriorSubClass;
     2181                PRTLOCKVALRECUNION  pDown;
     2182                RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
     2183                if (pPriorClass != NIL_RTLOCKVALCLASS)
    20552184                {
    2056                     Assert(   pClass != pPriorClass
    2057                            && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
    2058                     int rc = rtLockValidatorClassAddPriorClass(pClass, pFirstBadClass, true /*fAutodidacticism*/, pSrcPos);
    2059                     if (RT_FAILURE(rc))
     2185                    if (!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass))
    20602186                    {
    2061                         Assert(rc == VERR_NO_MEMORY);
    2062                         break;
     2187                        Assert(   pClass != pPriorClass
     2188                               && !rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
     2189                        int rc = rtLockValidatorClassAddPriorClass(pClass, pPriorClass, true /*fAutodidacticism*/, pSrcPos);
     2190                        if (RT_FAILURE(rc))
     2191                        {
     2192                            Assert(rc == VERR_NO_MEMORY);
     2193                            break;
     2194                        }
     2195                        Assert(rtLockValidatorClassIsPriorClass(pClass, pPriorClass));
    20632196                    }
    2064                     Assert(rtLockValidatorClassIsPriorClass(pPriorClass, pClass));
    20652197                }
     2198                pCur = pDown;
    20662199            }
    2067 
    2068             pCur = pDown;
    20692200        }
    20702201
     
    21132244        AssertPtrReturn(pCur, VERR_SEM_LV_INTERNAL_ERROR);
    21142245
    2115         uint32_t            uPriorSubClass;
    2116         PRTLOCKVALRECUNION  pDown;
    2117         RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
    2118         if (pPriorClass != NIL_RTLOCKVALCLASS)
    2119         {
    2120             AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
    2121             AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
    2122             if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)))
    2123                 return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos,
    2124                                                               pPriorClass, pCur, pDown);
    2125         }
    2126 
    2127         pCur = pDown;
     2246        if (pCur->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
     2247            pCur = pCur->Nest.pDown;
     2248        else
     2249        {
     2250            uint32_t            uPriorSubClass;
     2251            PRTLOCKVALRECUNION  pDown;
     2252            RTLOCKVALCLASSINT  *pPriorClass = rtLockValidatorRecGetClassesAndDown(pCur, &uPriorSubClass, &pDown);
     2253            if (pPriorClass != NIL_RTLOCKVALCLASS)
     2254            {
     2255                AssertPtrReturn(pPriorClass, VERR_SEM_LV_INTERNAL_ERROR);
     2256                AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_SEM_LV_INTERNAL_ERROR);
     2257                if (RT_UNLIKELY(!rtLockValidatorIsClassOrderOk(pClass, uSubClass, pPriorClass, uPriorSubClass)))
     2258                    return rtLockValidatorStackCheckLockingOrder2(pClass, uSubClass, pThreadSelf, pRec, pSrcPos,
     2259                                                                  pPriorClass, pCur, pDown);
     2260            }
     2261            pCur = pDown;
     2262        }
    21282263        if (!pCur)
    21292264            return VINF_SUCCESS;
     
    21532288        return VINF_SUCCESS;
    21542289
    2155     rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec);
     2290    rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec, true);
    21562291    rtLockValComplainPanic();
    21572292    return VERR_SEM_LV_WRONG_ORDER;
     
    25542689            default:            AssertFailed(); pszWhat = "!unexpected rc!"; break;
    25552690        }
    2556         rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL);
     2691        rtLockValComplainFirst(pszWhat, pSrcPos, pThreadSelf, pStack->a[0].pRec != pRec ? pRec : NULL, true);
    25572692        rtLockValComplainMore("---- start of deadlock chain - %u entries ----\n", pStack->c);
    25582693        for (uint32_t i = 0; i < pStack->c; i++)
     
    28052940    {
    28062941        rtLockValComplainFirst("Recursion not allowed by the class!",
    2807                                pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec);
     2942                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true);
    28082943        rtLockValComplainPanic();
    28092944        return VERR_SEM_LV_NESTED;
     
    28492984    {
    28502985        rtLockValComplainFirst("Mixed recursion not allowed by the class!",
    2851                                pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec);
     2986                               pSrcPos, pRecU->Excl.hThread, (PRTLOCKVALRECUNION)pRec, true);
    28522987        rtLockValComplainPanic();
    28532988        return VERR_SEM_LV_NESTED;
     
    29553090                && !pRecU->Excl.hClass->fRecursionOk))
    29563091        {
    2957             rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU);
     3092            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true);
    29583093            rtLockValComplainPanic();
    29593094            rc = VERR_SEM_LV_NESTED;
     
    31723307            )
    31733308        {
    3174             rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU);
     3309            rtLockValComplainFirst("Recursion not allowed!", pSrcPos, pThreadSelf, pRecU, true);
    31753310            rtLockValComplainPanic();
    31763311            rc =  VERR_SEM_LV_NESTED;
     
    36123747    if (RT_UNLIKELY(!pEntry))
    36133748    {
    3614         rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);
     3749        rtLockValComplainFirst("Not owner (shared)!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true);
    36153750        rtLockValComplainPanic();
    36163751        return VERR_SEM_LV_NOT_OWNER;
     
    36673802    if (RT_UNLIKELY(!pEntry))
    36683803    {
    3669         rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec);
     3804        rtLockValComplainFirst("Invalid signaller!", NULL, hThreadSelf, (PRTLOCKVALRECUNION)pRec, true);
    36703805        rtLockValComplainPanic();
    36713806        return VERR_SEM_LV_NOT_SIGNALLER;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette