VirtualBox

Changeset 25703 in vbox


Ignore:
Timestamp:
Jan 10, 2010 4:49:14 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56438
Message:

iprt/lockvalidator: Tested and debugged the basics of lock order validation.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/lockvalidator.h

    r25700 r25703  
    822822 * Releases a reference to a lock validator class.
    823823 *
    824  * @returns New reference count; UINT32_MAX if the handle is invalid.
     824 * @returns New reference count. 0 if hClass is NIL_RTLOCKVALCLASS. UINT32_MAX
     825 *          if the handle is invalid.
    825826 * @param   hClass              Handle to the class.
    826827 */
     
    840841
    841842/**
     843 * Enables or disables the strict release order enforcing.
     844 *
     845 * @returns IPRT status.
     846 * @param   hClass              Handle to the class to change.
     847 * @param   fEnable             Enable it (true) or disable it (false).
     848 */
     849RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled);
     850
     851/**
    842852 * Enables / disables the lock validator for new locks.
    843853 *
     
    867877 * @returns True if it is quiet, false if noisy.
    868878 */
    869 RTDECL(bool) RTLockValidatorAreQuiet(void);
     879RTDECL(bool) RTLockValidatorIsQuiet(void);
    870880
    871881/**
  • trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp

    r25701 r25703  
    6262/** Hashes the class handle (pointer) into an apPriorLocksHash index. */
    6363#define RTLOCKVALCLASS_HASH(hClass) \
    64     (   (uintptr_t)(hClass) \
     64    (   ((uintptr_t)(hClass) >> 6 ) \
    6565      % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
    6666         / sizeof(PRTLOCKVALCLASSREF)) )
     
    202202    RTLOCKVALCLASSREFCHUNK  PriorLocks;
    203203    /** Hash table containing frequently encountered prior locks. */
    204     PRTLOCKVALCLASSREF      apPriorLocksHash[11];
     204    PRTLOCKVALCLASSREF      apPriorLocksHash[17];
     205    /** Class name. (Allocated after the end of the block as usual.) */
     206    char const             *pszName;
     207    /** Where this class was created.
     208     *  This is mainly used for finding automatically created lock classes.
     209     *  @remarks The strings are stored after this structure so we won't crash
     210     *           if the class lives longer than the module (dll/so/dylib) that
     211     *           spawned it. */
     212    RTLOCKVALSRCPOS         CreatePos;
    205213#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
    206214    /** Hash hits. */
     
    209217    uint32_t volatile       cHashMisses;
    210218#endif
    211     /** Where this class was created.
    212      *  This is mainly used for finding automatically created lock classes.
    213      *  @remarks The strings are stored after this structure so we won't crash
    214      *           if the class lives longer than the module (dll/so/dylib) that
    215      *           spawned it. */
    216     RTLOCKVALSRCPOS         CreatePos;
    217     /** Class name. (Allocated after the end of the block as usual.) */
    218     char const             *pszName;
    219219} RTLOCKVALCLASSINT;
    220220AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32);
     
    251251#endif
    252252/** Serializing class tree insert and lookups. */
    253 static RTSEMRW          g_hLockValClassTreeRWLock = NIL_RTSEMRW;
     253static RTSEMRW          g_hLockValClassTreeRWLock= NIL_RTSEMRW;
    254254/** Class tree. */
    255 static PAVLLU32NODECORE g_LockValClassTree = NULL;
     255static PAVLLU32NODECORE g_LockValClassTree       = NULL;
    256256/** Critical section serializing the teaching new rules to the classes. */
    257257static RTCRITSECT       g_LockValClassTeachCS;
     
    10061006    for (unsigned i = 0; i < RT_ELEMENTS(pThis->apPriorLocksHash); i++)
    10071007        pThis->apPriorLocksHash[i] = NULL;
     1008    char *pszDst = (char *)(pThis + 1);
     1009    pThis->pszName              = (char *)memcpy(pszDst, szName, cbName);
     1010    pszDst += cbName;
    10081011    rtLockValidatorSrcPosCopy(&pThis->CreatePos, pSrcPos);
    1009     char *pszDst = (char *)(pThis + 1);
    10101012    pThis->CreatePos.pszFile    = pSrcPos->pszFile     ? (char *)memcpy(pszDst, pSrcPos->pszFile,     cbFile)     : NULL;
    10111013    pszDst += cbFile;
    10121014    pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL;
    1013     pszDst += cbFunction;
    10141015    Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key);
    1015     pThis->pszName              = (char *)memcpy(pszDst, szName, cbName);
     1016#ifdef RTLOCKVAL_WITH_CLASS_HASH_STATS
     1017    pThis->cHashHits            = 0;
     1018    pThis->cHashMisses          = 0;
     1019#endif
    10161020
    10171021    *phClass = pThis;
     
    10841088static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass)
    10851089{
    1086     AssertReturnVoid(pClass->fInTree);
     1090    AssertReturnVoid(!pClass->fInTree);
    10871091    ASMAtomicWriteU32(&pClass->u32Magic, RTLOCKVALCLASS_MAGIC_DEAD);
    10881092
     
    11041108        if (pChunk != &pClass->PriorLocks)
    11051109            RTMemFree(pChunk);
    1106         pNext = pChunk;
     1110        pChunk = pNext;
    11071111    }
    11081112
     
    11221126    {
    11231127        if (rtLockValidatorSrcPosCompare(&pClass->CreatePos, pSrcPos) == 0)
    1124         {
    1125             rtLockValidatorClassRetain(pClass);
    11261128            break;
    1127         }
    11281129        pClass = (RTLOCKVALCLASSINT *)pClass->Core.pList;
    11291130    }
     
    11791180{
    11801181    RTLOCKVALCLASSINT *pClass = hClass;
     1182    if (pClass == NIL_RTLOCKVALCLASS)
     1183        return 0;
    11811184    AssertPtrReturn(pClass, UINT32_MAX);
    11821185    AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, UINT32_MAX);
     
    13491352
    13501353    return rtLockValidatorClassAddPriorClass(pClass, pPriorClass, false /*fAutodidacticism*/, NULL);
     1354}
     1355
     1356
     1357RTDECL(int) RTLockValidatorClassEnforceStrictReleaseOrder(RTLOCKVALCLASS hClass, bool fEnabled)
     1358{
     1359    RTLOCKVALCLASSINT *pClass = hClass;
     1360    AssertPtrReturn(pClass, VERR_INVALID_HANDLE);
     1361    AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE);
     1362
     1363    ASMAtomicWriteBool(&pClass->fStrictReleaseOrder, fEnabled);
     1364    return VINF_SUCCESS;
    13511365}
    13521366
     
    20762090     * Something went wrong, pCur is pointing to where.
    20772091     */
    2078     if (rtLockValidatorClassIsPriorClass(pFirstBadClass, pClass))
     2092    if (   pClass == pFirstBadClass
     2093        || rtLockValidatorClassIsPriorClass(pFirstBadClass, pClass))
    20792094        return rtLockValidatorStackWrongOrder("Wrong locking order!", pSrcPos, pThreadSelf,
    20802095                                              pRec, pFirstBadRec, pClass, pFirstBadClass);
     
    22852300                  || (   pTop
    22862301                      && pTop->Core.u32Magic == RTLOCKVALRECNEST_MAGIC
    2287                       && pTop->Nest.pRec == pRec)))
     2302                      && pTop->Nest.pRec == pRec) ))
    22882303        return VINF_SUCCESS;
     2304
     2305#ifdef RTLOCKVAL_WITH_RECURSION_RECORDS
     2306    /* Look for a recursion record so the right frame is dumped and marked. */
     2307    while (pTop)
     2308    {
     2309        if (pTop->Core.u32Magic == RTLOCKVALRECNEST_MAGIC)
     2310        {
     2311            if (pTop->Nest.pRec == pRec)
     2312            {
     2313                pRec = pTop;
     2314                break;
     2315            }
     2316            pTop = pTop->Nest.pDown;
     2317        }
     2318        else if (pTop->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC)
     2319            pTop = pTop->Excl.pDown;
     2320        else if (pTop->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC)
     2321            pTop = pTop->ShrdOwner.pDown;
     2322        else
     2323            break;
     2324    }
     2325#endif
    22892326
    22902327    rtLockValComplainFirst("Wrong release order!", NULL, pThreadSelf, pRec, true);
    22912328    rtLockValComplainPanic();
    2292     return VERR_SEM_LV_WRONG_ORDER;
     2329    return VERR_SEM_LV_WRONG_RELEASE_ORDER;
    22932330}
    22942331
     
    28102847    ASMAtomicWriteU32(&pRec->Core.u32Magic, RTLOCKVALRECEXCL_MAGIC_DEAD);
    28112848    ASMAtomicWriteHandle(&pRec->hThread, NIL_RTTHREAD);
    2812     ASMAtomicWriteHandle(&pRec->hClass, NIL_RTLOCKVALCLASS);
     2849    RTLOCKVALCLASS hClass;
     2850    ASMAtomicXchgHandle(&pRec->hClass, NIL_RTLOCKVALCLASS, &hClass);
    28132851    if (pRec->pSibling)
    28142852        rtLockValidatorUnlinkAllSiblings(&pRec->Core);
    28152853    rtLockValidatorSerializeDestructLeave();
     2854    if (hClass != NIL_RTLOCKVALCLASS)
     2855        RTLockValidatorClassRelease(hClass);
    28162856}
    28172857
     
    30193059                                             PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies)
    30203060{
     3061    /*
     3062     * Validate and adjust input.  Quit early if order validation is disabled.
     3063     */
    30213064    PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec;
    30223065    AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECEXCL_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
     
    30343077    AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    30353078    Assert(hThreadSelf == RTThreadSelf());
     3079
     3080    /*
     3081     * Detect recursion as it isn't subject to order restrictions.
     3082     */
     3083    if (pRec->hThread == hThreadSelf)
     3084        return VINF_SUCCESS;
    30363085
    30373086    return rtLockValidatorStackCheckLockingOrder(pRecU->Excl.hClass, pRecU->Excl.uSubClass, hThreadSelf, pRecU, pSrcPos);
     
    32343283                                               PCRTLOCKVALSRCPOS pSrcPos, RTMSINTERVAL cMillies)
    32353284{
     3285    /*
     3286     * Validate and adjust input.  Quit early if order validation is disabled.
     3287     */
    32363288    PRTLOCKVALRECUNION pRecU = (PRTLOCKVALRECUNION)pRec;
    32373289    AssertReturn(pRecU->Core.u32Magic == RTLOCKVALRECSHRD_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
     
    32503302    AssertReturn(hThreadSelf->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    32513303    Assert(hThreadSelf == RTThreadSelf());
     3304
     3305    /*
     3306     * Detect recursion as it isn't subject to order restrictions.
     3307     */
     3308    PRTLOCKVALRECUNION pEntry = rtLockValidatorRecSharedFindOwner(&pRecU->Shared, hThreadSelf, NULL);
     3309    if (pEntry)
     3310        return VINF_SUCCESS;
    32523311
    32533312    return rtLockValidatorStackCheckLockingOrder(pRecU->Shared.hClass, pRecU->Shared.uSubClass, hThreadSelf, pRecU, pSrcPos);
     
    39604019
    39614020
    3962 RTDECL(bool) RTLockValidatorAreQuiet(void)
     4021RTDECL(bool) RTLockValidatorIsQuiet(void)
    39634022{
    39644023    return ASMAtomicUoReadBool(&g_fLockValidatorQuiet);
    39654024}
    3966 RT_EXPORT_SYMBOL(RTLockValidatorAreQuiet);
     4025RT_EXPORT_SYMBOL(RTLockValidatorIsQuiet);
    39674026
    39684027
  • trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp

    r25694 r25703  
    768768static void testLo1(void)
    769769{
    770     RTTestSub(g_hTest, "locking order, automatic");
    771 
    772     /* init, each critsect has its own class now. */
     770    RTTestSub(g_hTest, "locking order basics");
     771
     772    /* Initialize the critsections, the first 4 has their own classes, the rest
     773       use the same class and relies on the sub-class mechanism for ordering.  */
    773774    for (unsigned i = 0; i < RT_ELEMENTS(g_ahClasses); i++)
    774775    {
    775         RTTEST_CHECK_RC_RETV(g_hTest, RTLockValidatorClassCreate(&g_ahClasses[i], true /*fAutodidact*/, RT_SRC_POS), VINF_SUCCESS);
    776         RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectLO"), VINF_SUCCESS);
    777         RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 3);
    778         RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 2);
     776        if (i <= 3)
     777        {
     778            RTTEST_CHECK_RC_RETV(g_hTest, RTLockValidatorClassCreate(&g_ahClasses[i], true /*fAutodidact*/, RT_SRC_POS), VINF_SUCCESS);
     779            RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTCritSectLO-Auto"), VINF_SUCCESS);
     780            RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 3);
     781            RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 2);
     782        }
     783        else
     784        {
     785            g_ahClasses[i] = RTLockValidatorClassForSrcPos(RT_SRC_POS);
     786            RTTEST_CHECK_RETV(g_hTest, g_ahClasses[i] != NIL_RTLOCKVALCLASS);
     787            RTTEST_CHECK_RETV(g_hTest, i == 4 || g_ahClasses[i] == g_ahClasses[i - 1]);
     788            if (i == 4)
     789                RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE,     "RTCritSectLO-None"), VINF_SUCCESS);
     790            else if (i == 5)
     791                RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_ANY,      "RTCritSectLO-Any"), VINF_SUCCESS);
     792            else
     793                RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInitEx(&g_aCritSects[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_USER + i, "RTCritSectLO-User"), VINF_SUCCESS);
     794
     795            RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 1 + (i - 4 + 1) * 2); /* released in cleanup. */
     796        }
    779797    }
    780798
     
    807825
    808826    /* Check that recursion isn't subject to order checks. */
    809 
     827    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS);
     828    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS);
     829    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS);
     830    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS);
     831    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS);
     832    if (RT_SUCCESS(rc))
     833    {
     834        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS);
     835        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS);
     836        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS);
     837        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS);
     838
     839        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS);
     840        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS);
     841        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS);
     842        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS);
     843        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS);
     844    }
     845    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS);
     846    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS);
     847    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS);
     848    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS);
    810849
    811850    /* Enable strict release order for class 2 and check that violations
    812851       are caught. */
    813 
     852    RTTEST_CHECK_RC(g_hTest, RTLockValidatorClassEnforceStrictReleaseOrder(g_ahClasses[2], true), VINF_SUCCESS);
     853
     854    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS);
     855    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS);
     856    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS);
     857    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS);
     858
     859    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER);
     860    if (RT_FAILURE(rc))
     861    {
     862        /* applies to recursions as well */
     863        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS);
     864        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS);
     865        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER);
     866        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS);
     867        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS);
     868        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER);
     869    }
     870    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS);
     871    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS);
     872    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS);
     873    if (RT_FAILURE(rc))
     874        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS);
     875
     876    /* Test that sub-class order works (4 = NONE, 5 = ANY, 6+ = USER). */
     877    uint32_t cErrorsBefore = RTTestErrorCount(g_hTest);
     878    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[7]), VINF_SUCCESS);
     879
     880    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[4]), VERR_SEM_LV_WRONG_ORDER);
     881    if (RT_SUCCESS(rc))
     882        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[4]), VINF_SUCCESS);
     883
     884    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS);
     885    if (RT_SUCCESS(rc))
     886        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS);
     887
     888    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[8]), VINF_SUCCESS);
     889    if (RT_SUCCESS(rc))
     890        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[8]), VINF_SUCCESS);
     891
     892    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[6]), VERR_SEM_LV_WRONG_ORDER);
     893    if (RT_SUCCESS(rc))
     894        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[6]), VINF_SUCCESS);
     895
     896    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[7]), VINF_SUCCESS);
     897    if (RT_SUCCESS(rc))
     898        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[7]), VINF_SUCCESS);
     899    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[7]), VINF_SUCCESS);
     900
     901    /* Check that NONE trumps both ANY and USER. */
     902    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[4]), VINF_SUCCESS);
     903
     904    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[5]), VERR_SEM_LV_WRONG_ORDER);
     905    if (RT_SUCCESS(rc))
     906        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS);
     907
     908    RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(&g_aCritSects[6]), VERR_SEM_LV_WRONG_ORDER);
     909    if (RT_SUCCESS(rc))
     910        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[6]), VINF_SUCCESS);
     911
     912    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[4]), VINF_SUCCESS);
     913
     914    /* Take all the locks using sub-classes. */
     915    if (cErrorsBefore == RTTestErrorCount(g_hTest))
     916    {
     917        bool fSavedQuiet = RTLockValidatorSetQuiet(true);
     918        for (uint32_t i = 6; i < RT_ELEMENTS(g_aCritSects); i++)
     919        {
     920            RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[i]), VINF_SUCCESS);
     921            RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[4]), VERR_SEM_LV_WRONG_ORDER);
     922            RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS);
     923        }
     924        for (uint32_t i = 6; i < RT_ELEMENTS(g_aCritSects); i++)
     925        {
     926            RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[i]), VINF_SUCCESS);
     927            RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS);
     928        }
     929        RTLockValidatorSetQuiet(fSavedQuiet);
     930    }
     931
     932    /* Work up some hash statistics and trigger a violation to show them. */
     933    for (uint32_t i = 0; i < 10240; i++)
     934    {
     935        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[0]), VINF_SUCCESS);
     936        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[1]), VINF_SUCCESS);
     937        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[2]), VINF_SUCCESS);
     938        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VINF_SUCCESS);
     939        RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS);
     940
     941        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS);
     942        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[3]), VINF_SUCCESS);
     943        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[2]), VINF_SUCCESS);
     944        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[1]), VINF_SUCCESS);
     945        RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[0]), VINF_SUCCESS);
     946    }
     947    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[5]), VINF_SUCCESS);
     948    RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(&g_aCritSects[3]), VERR_SEM_LV_WRONG_ORDER);
     949    RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(&g_aCritSects[5]), VINF_SUCCESS);
    814950
    815951    /* clean up */
    816952    for (unsigned i = 0; i < RT_ELEMENTS(g_ahClasses); i++)
    817953    {
    818         RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 1);
     954        if (i <= 3)
     955            RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 1);
     956        else
     957        {
     958            uint32_t cExpect = 1 + (RT_ELEMENTS(g_ahClasses) - i) * 2 - 1;
     959            RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == cExpect);
     960        }
    819961        g_ahClasses[i] = NIL_RTLOCKVALCLASS;
    820962        RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
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