VirtualBox

Changeset 25711 in vbox


Ignore:
Timestamp:
Jan 11, 2010 11:15:04 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56449
Message:

iprt: RTSemMutex order validation.

Location:
trunk
Files:
7 edited

Legend:

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

    r25707 r25711  
    266266 *
    267267 * @returns iprt status code.
    268  * @param   pMutexSem   Where to store the mutex semaphore handle.
    269  */
    270 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem);
     268 * @param   phMutexSem      Where to store the mutex semaphore handle.
     269 */
     270RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem);
     271
     272/**
     273 * Creates a read/write semaphore.
     274 *
     275 * @returns iprt status code.
     276 * @param   phRWSem             Where to store the handle to the newly created
     277 *                              RW semaphore.
     278 * @param   fFlags              Flags, any combination of the
     279 *                              RTSEMMUTEX_FLAGS_XXX \#defines.
     280 * @param   hClass              The class (no reference consumed).  If NIL, no
     281 *                              lock order validation will be performed on this
     282 *                              lock.
     283 * @param   uSubClass           The sub-class.  This is used to define lock
     284 *                              order within a class.  RTLOCKVAL_SUB_CLASS_NONE
     285 *                              is the recommended value here.
     286 * @param   pszNameFmt          Name format string for the lock validator,
     287 *                              optional (NULL).  Max length is 32 bytes.
     288 * @param   ...                 Format string arguments.
     289 */
     290RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
     291                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...);
     292
     293/** @name RTSemMutexCreateEx flags
     294 * @{ */
     295/** Disables lock validation. */
     296#define RTSEMMUTEX_FLAGS_NO_LOCK_VAL    UINT32_C(0x00000001)
     297/** @} */
     298
    271299
    272300/**
     
    277305 */
    278306RTDECL(int)  RTSemMutexDestroy(RTSEMMUTEX MutexSem);
     307
     308/**
     309 * Changes the lock validator sub-class of the mutex semaphore.
     310 *
     311 * It is recommended to try make sure that nobody is using this sempahore while
     312 * changing the value.
     313 *
     314 * @returns The old sub-class.  RTLOCKVAL_SUB_CLASS_INVALID is returns if the
     315 *          lock validator isn't compiled in or either of the parameters are
     316 *          invalid.
     317 * @param   hMutexSem           The handle to the mutex semaphore.
     318 * @param   uSubClass           The new sub-class value.
     319 */
     320RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass);
    279321
    280322/**
     
    581623 *          lock validator isn't compiled in or either of the parameters are
    582624 *          invalid.
    583  * @param   hSemRW              The handle to the read/write semaphore.
     625 * @param   hRWSem              The handle to the read/write semaphore.
    584626 * @param   uSubClass           The new sub-class value.
    585627 */
  • trunk/src/VBox/Runtime/generic/semrw-generic.cpp

    r25710 r25711  
    121121            if (RT_SUCCESS(rc))
    122122            {
    123                 rc = RTCritSectInitEx(&pThis->CritSect, RTCRITSECT_FLAGS_NO_LOCK_VAL, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     123                rc = RTCritSectInitEx(&pThis->CritSect, RTCRITSECT_FLAGS_NO_LOCK_VAL,
     124                                      NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
    124125                if (RT_SUCCESS(rc))
    125126                {
  • trunk/src/VBox/Runtime/r3/linux/semmutex-linux.cpp

    r25704 r25711  
    107107
    108108
    109 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    110 {
     109#undef RTSemMutexCreate
     110RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
     111{
     112    return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     113}
     114
     115
     116RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
     117                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
     118{
     119    AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
     120
    111121    /*
    112122     * Allocate semaphore handle.
     
    120130        pThis->cNesting = 0;
    121131#ifdef RTSEMMUTEX_STRICT
    122         RTLockValidatorRecExclInit(&pThis->ValidatorRec, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, pThis,
    123                                    true /*fEnabled*/, "RTSemMutex");
    124 #endif
    125 
    126         *pMutexSem = pThis;
     132        va_list va;
     133        va_start(va, pszNameFmt);
     134        RTLockValidatorRecExclInitV(&pThis->ValidatorRec, hClass, uSubClass, pThis,
     135                                    !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
     136        va_end(va);
     137#endif
     138
     139        *phMutexSem = pThis;
    127140        return VINF_SUCCESS;
    128141    }
     
    165178    RTMemFree(pThis);
    166179    return VINF_SUCCESS;
     180}
     181
     182
     183RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
     184{
     185#ifdef RTSEMMUTEX_STRICT
     186    /*
     187     * Validate.
     188     */
     189    RTSEMMUTEXINTERNAL *pThis = hMutexSem;
     190    AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
     191    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
     192
     193    return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
     194#else
     195    return RTLOCKVAL_SUB_CLASS_INVALID;
     196#endif
    167197}
    168198
  • trunk/src/VBox/Runtime/r3/os2/sems-os2.cpp

    r25640 r25711  
    233233
    234234
    235 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    236 {
     235#undef RTSemMutexCreate
     236RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
     237{
     238    return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     239}
     240
     241
     242RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
     243                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
     244{
     245    AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
     246
    237247    /*
    238248     * Create the semaphore.
     
    242252    if (!rc)
    243253    {
    244         *pMutexSem = (RTSEMMUTEX)(void *)hmtx;
     254        /** @todo implement lock validation of OS/2 mutex semaphores. */
     255        *phMutexSem = (RTSEMMUTEX)(void *)hmtx;
    245256        return VINF_SUCCESS;
    246257    }
     
    260271    AssertMsgFailed(("Destroy MutexSem %p failed, rc=%d\n", MutexSem, rc));
    261272    return RTErrConvertFromOS2(rc);
     273}
     274
     275
     276
     277RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
     278{
     279#if 0 /** @todo def RTSEMMUTEX_STRICT */
     280    /*
     281     * Validate.
     282     */
     283    RTSEMMUTEXINTERNAL *pThis = hMutexSem;
     284    AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
     285    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
     286
     287    return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
     288#else
     289    return RTLOCKVAL_SUB_CLASS_INVALID;
     290#endif
    262291}
    263292
  • trunk/src/VBox/Runtime/r3/posix/semmutex-posix.cpp

    r25704 r25711  
    7171
    7272
    73 /* Undefine debug mappings. */
    74 #undef RTSemMutexRequest
    75 #undef RTSemMutexRequestNoResume
    76 
    77 
    78 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    79 {
     73#undef RTSemMutexCreate
     74RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
     75{
     76    return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     77}
     78
     79
     80RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
     81                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
     82{
     83    AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
     84
     85    /*
     86     * Allocate semaphore handle.
     87     */
    8088    int rc;
    81 
    82     /*
    83      * Allocate semaphore handle.
    84      */
    8589    struct RTSEMMUTEXINTERNAL *pThis = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
    8690    if (pThis)
     
    102106                pThis->u32Magic = RTSEMMUTEX_MAGIC;
    103107#ifdef RTSEMMUTEX_STRICT
    104                 RTLockValidatorRecExclInit(&pThis->ValidatorRec, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, pThis,
    105                                            true /*fEnabled*/, "RTSemMutex");
    106 #endif
    107 
    108                 *pMutexSem = pThis;
     108                va_list va;
     109                va_start(va, pszNameFmt);
     110                RTLockValidatorRecExclInitV(&pThis->ValidatorRec, hClass, uSubClass, pThis,
     111                                            !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
     112                va_end(va);
     113#endif
     114
     115                *phMutexSem = pThis;
    109116                return VINF_SUCCESS;
    110117            }
     
    153160
    154161    return VINF_SUCCESS;
     162}
     163
     164
     165RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
     166{
     167#ifdef RTSEMMUTEX_STRICT
     168    /*
     169     * Validate.
     170     */
     171    RTSEMMUTEXINTERNAL *pThis = hMutexSem;
     172    AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
     173    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
     174
     175    return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
     176#else
     177    return RTLOCKVAL_SUB_CLASS_INVALID;
     178#endif
    155179}
    156180
     
    256280
    257281
     282#undef RTSemMutexRequest
    258283RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
    259284{
     
    274299
    275300
     301#undef RTSemMutexRequestNoResume
    276302RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
    277303{
  • trunk/src/VBox/Runtime/r3/win/semmutex-win.cpp

    r25704 r25711  
    7070
    7171
    72 /* Undefine debug mappings. */
    73 #undef RTSemMutexRequest
    74 #undef RTSemMutexRequestNoResume
    75 
    76 
    77 RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    78 {
     72
     73#undef RTSemMutexCreate
     74RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
     75{
     76    return RTSemMutexCreateEx(phMutexSem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
     77}
     78
     79
     80RTDECL(int) RTSemMutexCreateEx(PRTSEMMUTEX phMutexSem, uint32_t fFlags,
     81                               RTLOCKVALCLASS hClass, uint32_t uSubClass, const char *pszNameFmt, ...)
     82{
     83    AssertReturn(!(fFlags & ~RTSEMMUTEX_FLAGS_NO_LOCK_VAL), VERR_INVALID_PARAMETER);
     84
     85    /*
     86     * Create the semaphore.
     87     */
    7988    int rc;
    80 
    81     /*
    82      * Create the semaphore.
    83      */
    8489    HANDLE hMtx = CreateMutex(NULL, FALSE, NULL);
    8590    if (hMtx)
     
    9398            pThis->cRecursions  = 0;
    9499#ifdef RTSEMMUTEX_STRICT
    95             RTLockValidatorRecExclInit(&pThis->ValidatorRec, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, pThis,
    96                                        true /*fEnabled*/, "RTSemMutex");
    97 #endif
    98             *pMutexSem = pThis;
     100            va_list va;
     101            va_start(va, pszNameFmt);
     102            RTLockValidatorRecExclInitV(&pThis->ValidatorRec, hClass, uSubClass, pThis,
     103                                        !(fFlags & RTSEMMUTEX_FLAGS_NO_LOCK_VAL), pszNameFmt, va);
     104            va_end(va);
     105#endif
     106            *phMutexSem = pThis;
    99107            return VINF_SUCCESS;
    100108        }
     
    138146    RTMemFree(pThis);
    139147    return rc;
     148}
     149
     150
     151RTDECL(uint32_t) RTSemMutexSetSubClass(RTSEMMUTEX hMutexSem, uint32_t uSubClass)
     152{
     153#ifdef RTSEMMUTEX_STRICT
     154    /*
     155     * Validate.
     156     */
     157    RTSEMMUTEXINTERNAL *pThis = hMutexSem;
     158    AssertPtrReturn(pThis, RTLOCKVAL_SUB_CLASS_INVALID);
     159    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, RTLOCKVAL_SUB_CLASS_INVALID);
     160
     161    return RTLockValidatorRecExclSetSubClass(&pThis->ValidatorRec, uSubClass);
     162#else
     163    return RTLOCKVAL_SUB_CLASS_INVALID;
     164#endif
    140165}
    141166
     
    225250
    226251
     252#undef RTSemMutexRequestNoResume
    227253RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
    228254{
  • trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp

    r25710 r25711  
    11161116
    11171117
     1118static void testLo4(void)
     1119{
     1120    RTTestSub(g_hTest, "locking order, mutex");
     1121
     1122    /* Initialize the critsection with all different classes */
     1123    for (unsigned i = 0; i < 4; i++)
     1124    {
     1125        RTTEST_CHECK_RC_RETV(g_hTest, RTLockValidatorClassCreate(&g_ahClasses[i], true /*fAutodidact*/, RT_SRC_POS, "testLo4-%u", i), VINF_SUCCESS);
     1126        RTTEST_CHECK_RC_RETV(g_hTest, RTSemMutexCreateEx(&g_ahSemMtxes[i], 0, g_ahClasses[i], RTLOCKVAL_SUB_CLASS_NONE, "RTSemMutexLo4-%u", i), VINF_SUCCESS);
     1127        RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRetain(g_ahClasses[i]) == 3);
     1128        RTTEST_CHECK_RETV(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 2);
     1129    }
     1130
     1131    /* Check the sub-class API.*/
     1132    RTTEST_CHECK(g_hTest, RTSemMutexSetSubClass(g_ahSemMtxes[0], RTLOCKVAL_SUB_CLASS_ANY)  == RTLOCKVAL_SUB_CLASS_NONE);
     1133    RTTEST_CHECK(g_hTest, RTSemMutexSetSubClass(g_ahSemMtxes[0], RTLOCKVAL_SUB_CLASS_NONE) == RTLOCKVAL_SUB_CLASS_ANY);
     1134
     1135    /* Enter the first 4 critsects in ascending order and thereby definining
     1136       this as a valid lock order.  */
     1137    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[0], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1138    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[1], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1139    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[2], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1140    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[3], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1141
     1142    /* Now, leave and re-enter the critsects in a way that should break the
     1143       order and check that we get the appropriate response. */
     1144    int rc;
     1145    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[0]), VINF_SUCCESS);
     1146    RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(g_ahSemMtxes[0], RT_INDEFINITE_WAIT), VERR_SEM_LV_WRONG_ORDER);
     1147    if (RT_SUCCESS(rc))
     1148        RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[0]), VINF_SUCCESS);
     1149
     1150    /* Check that recursion isn't subject to order checks. */
     1151    RTTEST_CHECK_RC(g_hTest, rc = RTSemMutexRequest(g_ahSemMtxes[1], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1152    if (RT_SUCCESS(rc))
     1153        RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[1]), VINF_SUCCESS);
     1154
     1155    /* Enable strict release order for class 2 and check that violations
     1156       are caught - including recursion. */
     1157    RTTEST_CHECK_RC(g_hTest, RTLockValidatorClassEnforceStrictReleaseOrder(g_ahClasses[2], true), VINF_SUCCESS);
     1158
     1159    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[2], RT_INDEFINITE_WAIT), VINF_SUCCESS);  /* start recursion */
     1160    RTTEST_CHECK_RC(g_hTest, RTSemMutexRequest(g_ahSemMtxes[3], RT_INDEFINITE_WAIT), VINF_SUCCESS);
     1161    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER);
     1162    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[3]), VINF_SUCCESS);
     1163    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[2]), VINF_SUCCESS);                      /* end recursion */
     1164
     1165    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[2]), VERR_SEM_LV_WRONG_RELEASE_ORDER);
     1166    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[1]), VINF_SUCCESS);
     1167    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[3]), VINF_SUCCESS);
     1168    RTTEST_CHECK_RC(g_hTest, RTSemMutexRelease(g_ahSemMtxes[2]), VINF_SUCCESS);
     1169
     1170    /* clean up */
     1171    for (unsigned i = 0; i < 4; i++)
     1172    {
     1173        RTTEST_CHECK(g_hTest, RTLockValidatorClassRelease(g_ahClasses[i]) == 1);
     1174        g_ahClasses[i] = NIL_RTLOCKVALCLASS;
     1175        RTTEST_CHECK_RC_RETV(g_hTest, RTSemMutexDestroy(g_ahSemMtxes[i]), VINF_SUCCESS);
     1176    }
     1177}
     1178
     1179
     1180
     1181
    11181182static bool testIsLockValidationCompiledIn(void)
    11191183{
     
    12091273        testLo2();
    12101274        testLo3();
     1275        testLo4();
    12111276    }
    12121277
Note: See TracChangeset for help on using the changeset viewer.

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