VirtualBox

Changeset 25373 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Dec 14, 2009 7:20:27 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55992
Message:

IPRT,PDMCritSect: More validation changes. Validate posix and linux mutexes. Always update the thread state with critsects.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/semmutex-posix.cpp

    r8651 r25373  
    3333*******************************************************************************/
    3434#include <iprt/semaphore.h>
     35#include "internal/iprt.h"
     36
     37#include <iprt/alloc.h>
     38#include <iprt/asm.h>
    3539#include <iprt/assert.h>
    36 #include <iprt/alloc.h>
     40#include <iprt/err.h>
     41#include <iprt/lockvalidator.h>
    3742#include <iprt/thread.h>
    38 #include <iprt/asm.h>
    39 #include <iprt/err.h>
     43#include "internal/magics.h"
    4044#include "internal/strict.h"
    4145
     
    5862    /** Nesting count. */
    5963    volatile uint32_t   cNesting;
     64    /** Magic value (RTSEMMUTEX_MAGIC). */
     65    uint32_t            u32Magic;
     66#ifdef RTSEMMUTEX_STRICT
     67    /** Lock validator record associated with this mutex. */
     68    RTLOCKVALIDATORREC  ValidatorRec;
     69#endif
    6070};
    6171
    6272
    6373
    64 /**
    65  * Validate a Mutex semaphore handle passed to one of the interface.
    66  *
    67  * @returns true if valid.
    68  * @returns false if invalid.
    69  * @param   pIntMutexSem    Pointer to the mutex semaphore to validate.
    70  */
    71 DECLINLINE(bool) rtsemMutexValid(struct RTSEMMUTEXINTERNAL *pIntMutexSem)
    72 {
    73     if ((uintptr_t)pIntMutexSem < 0x10000)
    74         return false;
    75 
    76     if (pIntMutexSem->cNesting == (uint32_t)~0)
    77         return false;
    78 
    79     return true;
    80 }
    81 
    82 
    8374RTDECL(int)  RTSemMutexCreate(PRTSEMMUTEX pMutexSem)
    8475{
     
    8879     * Allocate semaphore handle.
    8980     */
    90     struct RTSEMMUTEXINTERNAL *pIntMutexSem = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
    91     if (pIntMutexSem)
     81    struct RTSEMMUTEXINTERNAL *pThis = (struct RTSEMMUTEXINTERNAL *)RTMemAlloc(sizeof(struct RTSEMMUTEXINTERNAL));
     82    if (pThis)
    9283    {
    9384        /*
     
    9889        if (!rc)
    9990        {
    100             rc = pthread_mutex_init(&pIntMutexSem->Mutex, &MutexAttr);
     91            rc = pthread_mutex_init(&pThis->Mutex, &MutexAttr);
    10192            if (!rc)
    10293            {
    10394                pthread_mutexattr_destroy(&MutexAttr);
    10495
    105                 pIntMutexSem->Owner    = (pthread_t)-1;
    106                 pIntMutexSem->cNesting = 0;
    107 
    108                 *pMutexSem = pIntMutexSem;
     96                pThis->Owner    = (pthread_t)-1;
     97                pThis->cNesting = 0;
     98                pThis->u32Magic = RTSEMMUTEX_MAGIC;
     99#ifdef RTSEMMUTEX_STRICT
     100                RTLockValidatorInit(&pThis->ValidatorRec, NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_NONE, NULL, pThis);
     101#endif
     102
     103                *pMutexSem = pThis;
    109104                return VINF_SUCCESS;
    110105            }
    111106            pthread_mutexattr_destroy(&MutexAttr);
    112107        }
    113         RTMemFree(pIntMutexSem);
     108        RTMemFree(pThis);
    114109    }
    115110    else
     
    125120     * Validate input.
    126121     */
    127     if (!rtsemMutexValid(MutexSem))
    128     {
    129         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    130         return VERR_INVALID_HANDLE;
    131     }
     122    if (MutexSem == NIL_RTSEMMUTEX)
     123        return VINF_SUCCESS;
     124    struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
     125    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     126    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
    132127
    133128    /*
    134129     * Try destroy it.
    135130     */
    136     struct RTSEMMUTEXINTERNAL *pIntMutexSem = MutexSem;
    137     int rc = pthread_mutex_destroy(&pIntMutexSem->Mutex);
     131    int rc = pthread_mutex_destroy(&pThis->Mutex);
    138132    if (rc)
    139133    {
     
    145139     * Free the memory and be gone.
    146140     */
    147     pIntMutexSem->Owner    = (pthread_t)-1;
    148     pIntMutexSem->cNesting = ~0;
    149     RTMemTmpFree(pIntMutexSem);
     141    ASMAtomicWriteU32(&pThis->u32Magic, RTSEMMUTEX_MAGIC_DEAD);
     142    pThis->Owner    = (pthread_t)-1;
     143    pThis->cNesting = UINT32_MAX;
     144#ifdef RTSEMMUTEX_STRICT
     145    RTLockValidatorDelete(&pThis->ValidatorRec);
     146#endif
     147    RTMemTmpFree(pThis);
    150148
    151149    return VINF_SUCCESS;
     
    153151
    154152
    155 RTDECL(int)  RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
     153DECL_FORCE_INLINE(int) rtSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies, RTSEMMUTEX_STRICT_POS_DECL)
    156154{
    157155    /*
    158156     * Validate input.
    159157     */
    160     if (!rtsemMutexValid(MutexSem))
    161     {
    162         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    163         return VERR_INVALID_HANDLE;
    164     }
     158    struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
     159    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     160    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
     161
     162#ifdef RTSEMMUTEX_STRICT
     163    RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt();
     164    RTLockValidatorCheckOrder(&pThis->ValidatorRec, hThreadSelf, RTSEMMUTEX_STRICT_POS_ARGS);
     165#endif
    165166
    166167    /*
    167168     * Check if nested request.
    168169     */
    169     pthread_t                     Self = pthread_self();
    170     struct RTSEMMUTEXINTERNAL    *pIntMutexSem = MutexSem;
    171     if (    pIntMutexSem->Owner == Self
    172         &&  pIntMutexSem->cNesting > 0)
    173     {
    174         pIntMutexSem->cNesting++;
     170    pthread_t Self = pthread_self();
     171    if (    pThis->Owner == Self
     172        &&  pThis->cNesting > 0)
     173    {
     174        ASMAtomicIncU32(&pThis->cNesting);
    175175        return VINF_SUCCESS;
    176176    }
     177#ifndef RTSEMMUTEX_STRICT
     178    RTTHREAD hThreadSelf = RTThreadSelf();
     179#endif
    177180
    178181    /*
     
    182185    {
    183186        /* take mutex */
    184         int rc = pthread_mutex_lock(&pIntMutexSem->Mutex);
     187        RTThreadBlocking(hThreadSelf, RTTHREADSTATE_MUTEX, RTSEMMUTEX_STRICT_BLOCK_ARGS(&pThis->ValidatorRec));
     188        int rc = pthread_mutex_lock(&pThis->Mutex);
     189        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
    185190        if (rc)
    186191        {
     
    209214                ts.tv_sec++;
    210215            }
     216            RTThreadBlocking(hThreadSelf, RTTHREADSTATE_MUTEX, RTSEMMUTEX_STRICT_BLOCK_ARGS(&pThis->ValidatorRec));
    211217        }
    212218
    213219        /* take mutex */
    214         int rc = pthread_mutex_timedlock(&pIntMutexSem->Mutex, &ts);
     220        int rc = pthread_mutex_timedlock(&pThis->Mutex, &ts);
     221        RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
    215222        if (rc)
    216223        {
     
    224231     * Set the owner and nesting.
    225232     */
    226     pIntMutexSem->Owner = Self;
    227     ASMAtomicXchgU32(&pIntMutexSem->cNesting, 1);
    228 #ifdef RTSEMMUTEX_STRICT
    229     RTTHREAD Thread = RTThreadSelf();
    230     if (Thread != NIL_RTTHREAD)
    231         RTThreadWriteLockInc(Thread);
     233    pThis->Owner = Self;
     234    ASMAtomicWriteU32(&pThis->cNesting, 1);
     235#ifdef RTSEMMUTEX_STRICT
     236    RTThreadWriteLockInc(RTLockValidatorSetOwner(&pThis->ValidatorRec, hThreadSelf, RTSEMMUTEX_STRICT_POS_ARGS));
    232237#endif
    233238
     
    236241
    237242
    238 RTDECL(int)  RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
     243RTDECL(int) RTSemMutexRequest(RTSEMMUTEX MutexSem, unsigned cMillies)
     244{
     245#ifndef RTSEMMUTEX_STRICT
     246    return rtSemMutexRequest(MutexSem, cMillies, RTSEMMUTEX_STRICT_POS_ARGS);
     247#else
     248    return RTSemMutexRequestDebug(MutexSem, cMillies, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
     249#endif
     250}
     251
     252
     253RTDECL(int) RTSemMutexRequestDebug(RTSEMMUTEX MutexSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     254{
     255#ifdef RTSEMMUTEX_STRICT
     256    return rtSemMutexRequest(MutexSem, cMillies, RTSEMMUTEX_STRICT_POS_ARGS);
     257#else
     258    return RTSemMutexRequest(MutexSem, cMillies);
     259#endif
     260}
     261
     262
     263RTDECL(int) RTSemMutexRequestNoResume(RTSEMMUTEX MutexSem, unsigned cMillies)
    239264{
    240265    /* EINTR isn't returned by the wait functions we're using. */
     266#ifndef RTSEMMUTEX_STRICT
    241267    return RTSemMutexRequest(MutexSem, cMillies);
     268#else
     269    return RTSemMutexRequestDebug(MutexSem, cMillies, (uintptr_t)ASMReturnAddress(), RT_SRC_POS);
     270#endif
     271}
     272
     273
     274RTDECL(int) RTSemMutexRequestNoResumeDebug(RTSEMMUTEX MutexSem, unsigned cMillies, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     275{
     276    /* EINTR isn't returned by the wait functions we're using. */
     277#ifdef RTSEMMUTEX_STRICT
     278    return RTSemMutexRequestDebug(MutexSem, cMillies, RTSEMMUTEX_STRICT_POS_ARGS);
     279#else
     280    return RTSemMutexRequest(MutexSem, cMillies);
     281#endif
    242282}
    243283
     
    248288     * Validate input.
    249289     */
    250     if (!rtsemMutexValid(MutexSem))
    251     {
    252         AssertMsgFailed(("Invalid handle %p!\n", MutexSem));
    253         return VERR_INVALID_HANDLE;
    254     }
     290    struct RTSEMMUTEXINTERNAL *pThis = MutexSem;
     291    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     292    AssertReturn(pThis->u32Magic == RTSEMMUTEX_MAGIC, VERR_INVALID_HANDLE);
    255293
    256294    /*
    257295     * Check if nested.
    258296     */
    259     pthread_t                     Self = pthread_self();
    260     struct RTSEMMUTEXINTERNAL    *pIntMutexSem = MutexSem;
    261     if (    pIntMutexSem->Owner != Self
    262         ||  pIntMutexSem->cNesting == (uint32_t)~0)
     297    pthread_t Self = pthread_self();
     298    if (RT_UNLIKELY(    pThis->Owner != Self
     299                    ||  pThis->cNesting == 0))
    263300    {
    264301        AssertMsgFailed(("Not owner of mutex %p!! Self=%08x Owner=%08x cNesting=%d\n",
    265                          pIntMutexSem, Self, pIntMutexSem->Owner, pIntMutexSem->cNesting));
     302                         pThis, Self, pThis->Owner, pThis->cNesting));
    266303        return VERR_NOT_OWNER;
    267304    }
     
    270307     * If nested we'll just pop a nesting.
    271308     */
    272     if (pIntMutexSem->cNesting > 1)
    273     {
    274         pIntMutexSem->cNesting--;
     309    if (pThis->cNesting > 1)
     310    {
     311        ASMAtomicDecU32(&pThis->cNesting);
    275312        return VINF_SUCCESS;
    276313    }
     
    280317     */
    281318#ifdef RTSEMMUTEX_STRICT
    282     RTTHREAD Thread = RTThreadSelf();
    283     if (Thread != NIL_RTTHREAD)
    284         RTThreadWriteLockDec(Thread);
    285 #endif
    286     pIntMutexSem->Owner    = (pthread_t)-1;
    287     ASMAtomicXchgU32(&pIntMutexSem->cNesting, 0);
     319    RTThreadWriteLockDec(RTLockValidatorUnsetOwner(&pThis->ValidatorRec));
     320#endif
     321    pThis->Owner = (pthread_t)-1;
     322    ASMAtomicXchgU32(&pThis->cNesting, 0);
    288323
    289324    /*
    290325     * Unlock mutex semaphore.
    291326     */
    292     int rc = pthread_mutex_unlock(&pIntMutexSem->Mutex);
    293     if (rc)
     327    int rc = pthread_mutex_unlock(&pThis->Mutex);
     328    if (RT_UNLIKELY(rc))
    294329    {
    295330        AssertMsgFailed(("Failed to unlock mutex sem %p, rc=%d.\n", MutexSem, rc)); NOREF(rc);
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