VirtualBox

Changeset 25467 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Dec 17, 2009 3:16:55 PM (15 years ago)
Author:
vboxsync
Message:

IPRT,PDMCritSect: More lock validation.

File:
1 edited

Legend:

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

    r25436 r25467  
    181181RTDECL(int) RTLockValidatorCheckOrder(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    182182{
    183     AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_INVALID_MAGIC);
     183    AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    184184
    185185    /*
     
    196196
    197197
     198RTDECL(int)  RTLockValidatorCheckReleaseOrder(PRTLOCKVALIDATORREC pRec)
     199{
     200    AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
     201    AssertReturn(pRec->hThread != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER);
     202
     203    return VINF_SUCCESS;
     204}
     205
     206
     207RTDECL(int) RTLockValidatorRecordRecursion(PRTLOCKVALIDATORREC pRec, RTHCUINTPTR uId, RT_SRC_POS_DECL)
     208{
     209    AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
     210    AssertReturn(pRec->hThread != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER);
     211
     212    Assert(pRec->cRecursion < _1M);
     213    pRec->cRecursion++;
     214
     215    return VINF_SUCCESS;
     216}
     217
     218
     219RTDECL(void) RTLockValidatorRecordUnwind(PRTLOCKVALIDATORREC pRec)
     220{
     221    AssertReturnVoid(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC);
     222    AssertReturnVoid(pRec->hThread != NIL_RTTHREAD);
     223    AssertReturnVoid(pRec->cRecursion > 0);
     224
     225    pRec->cRecursion--;
     226}
     227
     228
    198229RTDECL(RTTHREAD) RTLockValidatorSetOwner(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, RTHCUINTPTR uId, RT_SRC_POS_DECL)
    199230{
     
    201232
    202233    if (hThread == NIL_RTTHREAD)
     234    {
    203235        hThread = RTThreadSelfAutoAdopt();
     236        AssertReturn(hThread != NIL_RTTHREAD, hThread);
     237    }
     238
     239    ASMAtomicIncS32(&hThread->LockValidator.cWriteLocks);
     240
    204241    if (pRec->hThread == hThread)
    205242        pRec->cRecursion++;
     
    232269{
    233270    AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, NIL_RTTHREAD);
    234     RTTHREAD hThread = pRec->hThread;
    235     AssertReturn(hThread != NIL_RTTHREAD, hThread);
    236     AssertReturn(pRec->hThread == hThread, hThread);
     271    RTTHREADINT *pThread = pRec->hThread;
     272    AssertReturn(pThread != NIL_RTTHREAD, pThread);
     273
     274    ASMAtomicDecS32(&pThread->LockValidator.cWriteLocks);
    237275
    238276    if (ASMAtomicDecU32(&pRec->cRecursion) == 0)
     
    249287    }
    250288
    251     return hThread;
     289    return pThread;
    252290}
    253291
     
    421459
    422460
    423 /**
    424  * Change the thread state to blocking and do deadlock detection.
    425  *
    426  * @param   pRec                The validator record we're blocing on.
    427  * @param   hThread             The current thread.  Shall not be NIL_RTTHREAD!
    428  * @param   enmState            The sleep state.
    429  * @param   pvBlock             Pointer to a RTLOCKVALIDATORREC structure.
    430  * @param   fRecursiveOk        Whether it's ok to recurse.
    431  * @param   uId                 Where we are blocking.
    432  * @param   RT_SRC_POS_DECL     Where we are blocking.
    433  */
    434 RTDECL(void) RTLockValidatorCheckBlocking(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread,
    435                                           RTTHREADSTATE enmState, bool fRecursiveOk,
    436                                           RTHCUINTPTR uId, RT_SRC_POS_DECL)
     461RTDECL(int) RTLockValidatorCheckBlocking(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread,
     462                                         RTTHREADSTATE enmState, bool fRecursiveOk,
     463                                         RTHCUINTPTR uId, RT_SRC_POS_DECL)
    437464{
    438465    /*
    439466     * Fend off wild life.
    440467     */
    441     AssertReturnVoid(RTTHREAD_IS_SLEEPING(enmState));
    442     AssertPtrReturnVoid(pRec);
    443     AssertReturnVoid(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC);
     468    AssertReturn(RTTHREAD_IS_SLEEPING(enmState), VERR_SEM_LV_INVALID_PARAMETER);
     469    AssertPtrReturn(pRec, VERR_SEM_LV_INVALID_PARAMETER);
     470    AssertReturn(pRec->u32Magic == RTLOCKVALIDATORREC_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    444471    PRTTHREADINT pThread = hThread;
    445     AssertPtrReturnVoid(pThread);
    446     AssertReturnVoid(pThread->u32Magic == RTTHREADINT_MAGIC);
     472    AssertPtrReturn(pThread, VERR_SEM_LV_INVALID_PARAMETER);
     473    AssertReturn(pThread->u32Magic == RTTHREADINT_MAGIC, VERR_SEM_LV_INVALID_PARAMETER);
    447474    RTTHREADSTATE enmThreadState = rtThreadGetState(pThread);
    448     AssertReturnVoid(   enmThreadState == RTTHREADSTATE_RUNNING
    449                      || enmThreadState == RTTHREADSTATE_TERMINATED /* rtThreadRemove uses locks too */);
     475    AssertReturn(   enmThreadState == RTTHREADSTATE_RUNNING
     476                 || enmThreadState == RTTHREADSTATE_TERMINATED   /* rtThreadRemove uses locks too */
     477                 || enmThreadState == RTTHREADSTATE_INITIALIZING /* rtThreadInsert uses locks too */
     478                 , VERR_SEM_LV_INVALID_PARAMETER);
    450479
    451480    /*
     
    468497     * isn't any other place to check for this.  semmutex-win.cpp for instance.
    469498     */
    470     if (    !fRecursiveOk
    471         ||  pRec->hThread != pThread)
    472     {
    473         /*
    474          * Do deadlock detection.
    475          *
    476          * Since we're missing proper serialization, we don't declare it a
    477          * deadlock until we've got three runs with the same list length.
    478          * While this isn't perfect, it should avoid out the most obvious
    479          * races on SMP boxes.
    480          */
    481         rtLockValidatorSerializeDetectionEnter();
    482 
    483         PRTTHREADINT    pCur;
    484         unsigned        cPrevLength = ~0U;
    485         unsigned        cEqualRuns  = 0;
    486         unsigned        iParanoia   = 256;
    487         do
     499    if (pRec->hThread == pThread)
     500    {
     501        if (fRecursiveOk)
     502            return VINF_SUCCESS;
     503        AssertMsgFailed(("%p (%s)\n", pRec->hLock, pRec->pszName));
     504        return VERR_SEM_LV_NESTED;
     505    }
     506
     507    /*
     508     * Do deadlock detection.
     509     *
     510     * Since we're missing proper serialization, we don't declare it a
     511     * deadlock until we've got three runs with the same list length.
     512     * While this isn't perfect, it should avoid out the most obvious
     513     * races on SMP boxes.
     514     */
     515    rtLockValidatorSerializeDetectionEnter();
     516
     517    PRTTHREADINT    pCur;
     518    unsigned        cPrevLength = ~0U;
     519    unsigned        cEqualRuns  = 0;
     520    unsigned        iParanoia   = 256;
     521    do
     522    {
     523        unsigned cLength = 0;
     524        pCur = pThread;
     525        for (;;)
    488526        {
    489             unsigned cLength = 0;
    490             pCur = pThread;
     527            /*
     528             * Get the next thread.
     529             */
     530            PRTTHREADINT pNext = NULL;
    491531            for (;;)
    492532            {
    493                 /*
    494                  * Get the next thread.
    495                  */
    496                 PRTTHREADINT pNext = NULL;
    497                 for (;;)
     533                RTTHREADSTATE enmCurState = rtThreadGetState(pCur);
     534                switch (enmCurState)
    498535                {
    499                     RTTHREADSTATE enmCurState = rtThreadGetState(pCur);
    500                     switch (enmCurState)
     536                    case RTTHREADSTATE_CRITSECT:
     537                    case RTTHREADSTATE_EVENT:
     538                    case RTTHREADSTATE_EVENT_MULTI:
     539                    case RTTHREADSTATE_FAST_MUTEX:
     540                    case RTTHREADSTATE_MUTEX:
     541                    case RTTHREADSTATE_RW_READ:
     542                    case RTTHREADSTATE_RW_WRITE:
     543                    case RTTHREADSTATE_SPIN_MUTEX:
    501544                    {
    502                         case RTTHREADSTATE_CRITSECT:
    503                         case RTTHREADSTATE_EVENT:
    504                         case RTTHREADSTATE_EVENT_MULTI:
    505                         case RTTHREADSTATE_FAST_MUTEX:
    506                         case RTTHREADSTATE_MUTEX:
    507                         case RTTHREADSTATE_RW_READ:
    508                         case RTTHREADSTATE_RW_WRITE:
    509                         case RTTHREADSTATE_SPIN_MUTEX:
    510                         {
    511                             PRTLOCKVALIDATORREC pCurRec = pCur->LockValidator.pRec;
    512                             if (    rtThreadGetState(pCur) != enmCurState
    513                                 ||  !VALID_PTR(pCurRec)
    514                                 ||  pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC)
    515                                 continue;
    516                             pNext = pCurRec->hThread;
    517                             if (    rtThreadGetState(pCur) != enmCurState
    518                                 ||  pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC
    519                                 ||  pCurRec->hThread != pNext)
    520                                 continue;
    521                             break;
    522                         }
    523 
    524                         default:
    525                             pNext = NULL;
    526                             break;
     545                        PRTLOCKVALIDATORREC pCurRec = pCur->LockValidator.pRec;
     546                        if (    rtThreadGetState(pCur) != enmCurState
     547                            ||  !VALID_PTR(pCurRec)
     548                            ||  pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC)
     549                            continue;
     550                        pNext = pCurRec->hThread;
     551                        if (    rtThreadGetState(pCur) != enmCurState
     552                            ||  pCurRec->u32Magic != RTLOCKVALIDATORREC_MAGIC
     553                            ||  pCurRec->hThread != pNext)
     554                            continue;
     555                        break;
    527556                    }
    528                     break;
     557
     558                    default:
     559                        pNext = NULL;
     560                        break;
    529561                }
    530 
    531                 /*
    532                  * If we arrive at the end of the list we're good.
    533                  */
    534                 pCur = pNext;
    535                 if (!pCur)
    536                 {
    537                     rtLockValidatorSerializeDetectionLeave();
    538                     return;
    539                 }
    540 
    541                 /*
    542                  * If we've got back to the blocking thread id we've
    543                  * got a deadlock.
    544                  */
    545                 if (pCur == pThread)
    546                     break;
    547 
    548                 /*
    549                  * If we've got a chain of more than 256 items, there is some
    550                  * kind of cycle in the list, which means that there is already
    551                  * a deadlock somewhere.
    552                  */
    553                 if (cLength >= 256)
    554                     break;
    555 
    556                 cLength++;
     562                break;
    557563            }
    558564
    559             /* compare with previous list run. */
    560             if (cLength != cPrevLength)
     565            /*
     566             * If we arrive at the end of the list we're good.
     567             */
     568            pCur = pNext;
     569            if (!pCur)
    561570            {
    562                 cPrevLength = cLength;
    563                 cEqualRuns = 0;
     571                rtLockValidatorSerializeDetectionLeave();
     572                return VINF_SUCCESS;
    564573            }
    565             else
    566                 cEqualRuns++;
    567         } while (cEqualRuns < 3 && --iParanoia > 0);
    568 
    569         /*
    570          * Ok, if we ever get here, it's most likely a genuine deadlock.
    571          */
    572         rtLockValidatorComplainAboutDeadlock(pRec, pThread, enmState, pCur, uId, RT_SRC_POS_ARGS);
    573 
    574         rtLockValidatorSerializeDetectionLeave();
    575     }
     574
     575            /*
     576             * If we've got back to the blocking thread id we've
     577             * got a deadlock.
     578             */
     579            if (pCur == pThread)
     580                break;
     581
     582            /*
     583             * If we've got a chain of more than 256 items, there is some
     584             * kind of cycle in the list, which means that there is already
     585             * a deadlock somewhere.
     586             */
     587            if (cLength >= 256)
     588                break;
     589
     590            cLength++;
     591        }
     592
     593        /* compare with previous list run. */
     594        if (cLength != cPrevLength)
     595        {
     596            cPrevLength = cLength;
     597            cEqualRuns = 0;
     598        }
     599        else
     600            cEqualRuns++;
     601    } while (cEqualRuns < 3 && --iParanoia > 0);
     602
     603    /*
     604     * Ok, if we ever get here, it's most likely a genuine deadlock.
     605     */
     606    rtLockValidatorComplainAboutDeadlock(pRec, pThread, enmState, pCur, uId, RT_SRC_POS_ARGS);
     607
     608    rtLockValidatorSerializeDetectionLeave();
     609
     610    return VERR_SEM_LV_DEADLOCK;
    576611}
    577612RT_EXPORT_SYMBOL(RTThreadBlocking);
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