VirtualBox

Changeset 25368 in vbox for trunk/src/VBox/Runtime/generic


Ignore:
Timestamp:
Dec 14, 2009 4:31:40 PM (15 years ago)
Author:
vboxsync
Message:

RTCritSect,PDMCritSect,iprt/lockvalidator.h: Reworked the deadlocking detection for critical sections and preparing for lock order validation. This change generalizes the RTCRITSECT::Strict data and moves it out of the RTCRITSECT, leaving a pointer behind. This saves a bit of space in release builds.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/generic/critsect-generic.cpp

    r23718 r25368  
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    4545
    4646
    47 /* in strict mode we're redefining this, so undefine it now for the implementation. */
     47/* In strict mode we're redefining these, so undefine them now for the implementation. */
    4848#undef RTCritSectEnter
    4949#undef RTCritSectTryEnter
     
    5151
    5252
    53 /**
    54  * Initialize a critical section.
    55  */
    5653RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect)
    5754{
     
    6158
    6259
    63 /**
    64  * Initialize a critical section.
    65  *
    66  * @returns iprt status code.
    67  * @param   pCritSect   Pointer to the critical section structure.
    68  * @param   fFlags      Flags, any combination of the RTCRITSECT_FLAGS \#defines.
    69  */
    7060RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags)
    7161{
     
    7868    pCritSect->cLockers             = -1;
    7969    pCritSect->NativeThreadOwner    = NIL_RTNATIVETHREAD;
    80     pCritSect->Strict.ThreadOwner   = NIL_RTTHREAD;
    81     pCritSect->Strict.pszEnterFile  = NULL;
    82     pCritSect->Strict.u32EnterLine  = 0;
    83     pCritSect->Strict.uEnterId      = 0;
    84     int rc = RTSemEventCreate(&pCritSect->EventSem);
     70    int rc = RTLockValidatorCreate(&pCritSect->pValidatorRec, NIL_RTLOCKVALIDATORCLASS, 0, NULL, pCritSect);
    8571    if (RT_SUCCESS(rc))
    86         return VINF_SUCCESS;
     72    {
     73        rc = RTSemEventCreate(&pCritSect->EventSem);
     74        if (RT_SUCCESS(rc))
     75            return VINF_SUCCESS;
     76        RTLockValidatorDestroy(&pCritSect->pValidatorRec);
     77    }
    8778
    8879    AssertRC(rc);
     
    9485
    9586
    96 /**
    97  * Enter multiple critical sections.
    98  *
    99  * This function will enter ALL the specified critical sections before returning.
    100  *
    101  * @returns VINF_SUCCESS on success.
    102  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    103  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    104  * @param   cCritSects      Number of critical sections in the array.
    105  * @param   papCritSects    Array of critical section pointers.
    106  *
    107  * @remark  Please note that this function will not necessarily come out favourable in a
    108  *          fight with other threads which are using the normal RTCritSectEnter() function.
    109  *          Therefore, avoid having to enter multiple critical sections!
    110  */
    111 RTDECL(int) RTCritSectEnterMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects)
    112 #ifdef RTCRITSECT_STRICT
    113 {
    114     return RTCritSectEnterMultipleDebug(cCritSects, papCritSects, __FILE__, __LINE__, 0);
    115 }
    116 RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    117 #endif /* RTCRITSECT_STRICT */
     87#ifdef RTCRITSECT_STRICT
     88RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
     89#else
     90RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
     91#endif
    11892{
    11993    Assert(cCritSects > 0);
    120     Assert(VALID_PTR(papCritSects));
     94    AssertPtr(papCritSects);
    12195
    12296    /*
     
    12498     */
    12599    int rc = VERR_INVALID_PARAMETER;
    126     unsigned i;
     100    size_t i;
    127101    for (i = 0; i < cCritSects; i++)
    128102    {
    129103#ifdef RTCRITSECT_STRICT
    130         rc = RTCritSectTryEnterDebug(papCritSects[i], pszFile, uLine, uId);
     104        rc = RTCritSectTryEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
    131105#else
    132106        rc = RTCritSectTryEnter(papCritSects[i]);
     
    146120         * We've failed, release any locks we might have gotten. ('i' is the lock that failed btw.)
    147121         */
    148         unsigned j = i;
     122        size_t j = i;
    149123        while (j-- > 0)
    150124        {
     
    166140         */
    167141#ifdef RTCRITSECT_STRICT
    168         rc = RTCritSectEnterDebug(papCritSects[i], pszFile, uLine, uId);
     142        rc = RTCritSectEnterDebug(papCritSects[i], uId, RT_SRC_POS_ARGS);
    169143#else
    170144        rc = RTCritSectEnter(papCritSects[i]);
     
    181155            {
    182156#ifdef RTCRITSECT_STRICT
    183                 rc = RTCritSectTryEnterDebug(papCritSects[j], pszFile, uLine, uId);
     157                rc = RTCritSectTryEnterDebug(papCritSects[j], uId, RT_SRC_POS_ARGS);
    184158#else
    185159                rc = RTCritSectTryEnter(papCritSects[j]);
     
    203177    }
    204178}
     179#ifdef RTCRITSECT_STRICT
     180RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
     181#else
    205182RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
    206 
    207 
    208 /**
    209  * Try enter a critical section.
    210  *
    211  * @returns VINF_SUCCESS on success.
    212  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    213  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    214  * @param   pCritSect   The critical section.
    215  */
     183#endif
     184
     185
     186#ifdef RTCRITSECT_STRICT
     187RTDECL(int) RTCritSectEnterMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
     188{
     189    return RTCritSectEnterMultipleDebug(cCritSects, papCritSects, 0, RT_SRC_POS);
     190}
     191RT_EXPORT_SYMBOL(RTCritSectEnterMultiple);
     192
     193
     194#else  /* !RTCRITSECT_STRICT */
     195RTDECL(int) RTCritSectEnterMultipleDebug(size_t cCritSects, PRTCRITSECT *papCritSects, RTUINTPTR uId, RT_SRC_POS_DECL)
     196{
     197    return RTCritSectEnterMultiple(cCritSects, papCritSects);
     198}
     199RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
     200#endif /* !RTCRITSECT_STRICT */
     201
     202
     203#ifdef RTCRITSECT_STRICT
     204RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     205#else
    216206RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
    217 #ifdef RTCRITSECT_STRICT
    218 {
    219     return RTCritSectTryEnterDebug(pCritSect, __FILE__, __LINE__, 0);
    220 }
    221 RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    222 #endif /* RTCRITSECT_STRICT */
     207#endif
    223208{
    224209    Assert(pCritSect);
     
    259244    ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
    260245#ifdef RTCRITSECT_STRICT
    261     pCritSect->Strict.pszEnterFile = pszFile;
    262     pCritSect->Strict.u32EnterLine = uLine;
    263     pCritSect->Strict.uEnterId     = uId;
    264     ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, ThreadSelf);
     246    RTLockValidatorSetOwner(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    265247#endif
    266248
    267249    return VINF_SUCCESS;
    268250}
     251#ifdef RTCRITSECT_STRICT
     252RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
     253#else
    269254RT_EXPORT_SYMBOL(RTCritSectTryEnter);
    270 
    271 
    272 /**
    273  * Enter a critical section.
    274  *
    275  * @returns VINF_SUCCESS on success.
    276  * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
    277  * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
    278  * @param   pCritSect   The critical section.
    279  */
     255#endif
     256
     257
     258#ifdef RTCRITSECT_STRICT
     259RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect)
     260{
     261    return RTCritSectTryEnterDebug(pCritSect, 0, RT_SRC_POS);
     262}
     263RT_EXPORT_SYMBOL(RTCritSectTryEnter);
     264
     265
     266#else  /* !RTCRITSECT_STRICT */
     267RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     268{
     269    return RTCritSectTryEnter(pCritSect);
     270}
     271RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
     272#endif /* !RTCRITSECT_STRICT */
     273
     274
     275#ifdef RTCRITSECT_STRICT
     276RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     277#else
    280278RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
    281 #ifdef RTCRITSECT_STRICT
    282 {
    283     return RTCritSectEnterDebug(pCritSect, __FILE__, __LINE__, 0);
    284 }
    285 RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    286 #endif /* RTCRITSECT_STRICT */
     279#endif
    287280{
    288281    Assert(pCritSect);
     
    293286    if (ThreadSelf == NIL_RTTHREAD)
    294287        RTThreadAdopt(RTTHREADTYPE_DEFAULT, 0, NULL, &ThreadSelf);
     288    RTLockValidatorCheckOrder(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    295289#endif
    296290
     
    324318        {
    325319#ifdef RTCRITSECT_STRICT
    326             RTThreadBlocking(ThreadSelf, RTTHREADSTATE_CRITSECT, (uintptr_t)pCritSect, pszFile, uLine, uId);
     320            RTThreadBlocking(ThreadSelf, RTTHREADSTATE_CRITSECT, pCritSect->pValidatorRec, uId, RT_SRC_POS_ARGS);
    327321#endif
    328322            int rc = RTSemEventWait(pCritSect->EventSem, RT_INDEFINITE_WAIT);
     
    345339    ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NativeThreadSelf);
    346340#ifdef RTCRITSECT_STRICT
    347     pCritSect->Strict.pszEnterFile = pszFile;
    348     pCritSect->Strict.u32EnterLine = uLine;
    349     pCritSect->Strict.uEnterId     = uId;
    350     ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, ThreadSelf);
     341    RTLockValidatorSetOwner(pCritSect->pValidatorRec, ThreadSelf, uId, RT_SRC_POS_ARGS);
    351342    RTThreadWriteLockInc(ThreadSelf);
    352343#endif
     
    354345    return VINF_SUCCESS;
    355346}
     347#ifdef RTCRITSECT_STRICT
     348RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
     349#else
    356350RT_EXPORT_SYMBOL(RTCritSectEnter);
    357 
    358 
    359 /**
    360  * Leave a critical section.
    361  *
    362  * @returns VINF_SUCCESS.
    363  * @param   pCritSect   The critical section.
    364  */
     351#endif
     352
     353
     354#ifdef RTCRITSECT_STRICT
     355RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect)
     356{
     357    return RTCritSectEnterDebug(pCritSect, 0, RT_SRC_POS);
     358}
     359RT_EXPORT_SYMBOL(RTCritSectEnter);
     360
     361
     362#else  /* !RTCRITSECT_STRICT */
     363RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     364{
     365    return RTCritSectEnter(pCritSect);
     366}
     367RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
     368#endif /* !RTCRITSECT_STRICT */
     369
     370
    365371RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect)
    366372{
     
    387393         */
    388394#ifdef RTCRITSECT_STRICT
    389         if (pCritSect->Strict.ThreadOwner != NIL_RTTHREAD) /* May happen for PDMCritSects when entering GC/R0. */
    390             RTThreadWriteLockDec(pCritSect->Strict.ThreadOwner);
    391         ASMAtomicWriteHandle(&pCritSect->Strict.ThreadOwner, NIL_RTTHREAD);
     395        RTLockValidatorUnsetOwner(pCritSect->pValidatorRec);
    392396#endif
    393397        ASMAtomicWriteHandle(&pCritSect->NativeThreadOwner, NIL_RTNATIVETHREAD);
     
    403407
    404408
    405 /**
    406  * Leave multiple critical sections.
    407  *
    408  * @returns VINF_SUCCESS.
    409  * @param   cCritSects      Number of critical sections in the array.
    410  * @param   papCritSects    Array of critical section pointers.
    411  */
    412 RTDECL(int) RTCritSectLeaveMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects)
     409RTDECL(int) RTCritSectLeaveMultiple(size_t cCritSects, PRTCRITSECT *papCritSects)
    413410{
    414411    int rc = VINF_SUCCESS;
    415     for (unsigned i = 0; i < cCritSects; i++)
     412    for (size_t i = 0; i < cCritSects; i++)
    416413    {
    417414        int rc2 = RTCritSectLeave(papCritSects[i]);
     
    424421
    425422
    426 #ifndef RTCRITSECT_STRICT
    427 RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    428 {
    429     return RTCritSectEnter(pCritSect);
    430 }
    431 
    432 RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    433 {
    434     return RTCritSectTryEnter(pCritSect);
    435 }
    436 
    437 RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId)
    438 {
    439     return RTCritSectEnterMultiple(cCritSects, papCritSects);
    440 }
    441 #endif /* RT_STRICT */
    442 RT_EXPORT_SYMBOL(RTCritSectEnterDebug);
    443 RT_EXPORT_SYMBOL(RTCritSectTryEnterDebug);
    444 RT_EXPORT_SYMBOL(RTCritSectEnterMultipleDebug);
    445 
    446 
    447 /**
    448  * Deletes a critical section.
    449  *
    450  * @returns VINF_SUCCESS.
    451  * @param   pCritSect   The critical section.
    452  */
    453423RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect)
    454424{
     
    472442    RTSEMEVENT EventSem = pCritSect->EventSem;
    473443    pCritSect->EventSem         = NIL_RTSEMEVENT;
     444
    474445    while (pCritSect->cLockers-- >= 0)
    475446        RTSemEventSignal(EventSem);
     
    478449    AssertRC(rc);
    479450
     451    RTLockValidatorDestroy(&pCritSect->pValidatorRec);
     452
    480453    return rc;
    481454}
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