VirtualBox

Ignore:
Timestamp:
Jan 2, 2010 12:14:47 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
56308
Message:

iprt: Added lock validator testcase for read-write semaphore deadlocks. Fixed bugs found with it.

File:
1 edited

Legend:

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

    r25614 r25617  
    8686/** Pointer to a deadlock detction stack. */
    8787typedef RTLOCKVALDDSTACK *PRTLOCKVALDDSTACK;
     88
     89
     90/*******************************************************************************
     91*   Defined Constants And Macros                                               *
     92*******************************************************************************/
     93/** Macro that asserts that a pointer is aligned correctly.
     94 * Only used when fighting bugs. */
     95#if 1
     96# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   \
     97    AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));
     98#else
     99# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   do { } while (0)
     100#endif
    88101
    89102
     
    121134DECL_FORCE_INLINE(PRTLOCKVALRECUNION) rtLockValidatorReadRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec)
    122135{
    123     return (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec);
     136    PRTLOCKVALRECUNION p = (PRTLOCKVALRECUNION)ASMAtomicReadPtr((void * volatile *)ppRec);
     137    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
     138    return p;
    124139}
    125140
     
    128143DECL_FORCE_INLINE(void) rtLockValidatorWriteRecUnionPtr(PRTLOCKVALRECUNION volatile *ppRec, PRTLOCKVALRECUNION pRecNew)
    129144{
     145    RTLOCKVAL_ASSERT_PTR_ALIGN(pRecNew);
    130146    ASMAtomicWritePtr((void * volatile *)ppRec, pRecNew);
    131147}
     
    135151DECL_FORCE_INLINE(PRTTHREADINT) rtLockValidatorReadThreadHandle(RTTHREAD volatile *phThread)
    136152{
    137     return (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread);
     153    PRTTHREADINT p = (PRTTHREADINT)ASMAtomicReadPtr((void * volatile *)phThread);
     154    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
     155    return p;
    138156}
    139157
     
    142160DECL_FORCE_INLINE(PRTLOCKVALRECSHRDOWN) rtLockValidatorUoReadSharedOwner(PRTLOCKVALRECSHRDOWN volatile *ppOwner)
    143161{
    144     return (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner);
     162    PRTLOCKVALRECSHRDOWN p = (PRTLOCKVALRECSHRDOWN)ASMAtomicUoReadPtr((void * volatile *)ppOwner);
     163    RTLOCKVAL_ASSERT_PTR_ALIGN(p);
     164    return p;
    145165}
    146166
     
    456476
    457477/**
    458  * Worker for rtLockValidatorDoDeadlockCheck that checks if there is more work
    459  * to be done during unwind.
    460  *
    461  * @returns true if there is more work left for this lock, false if not.
    462  * @param   pRec            The current record.
    463  * @param   iEntry          The current index.
    464  * @param   pFirstSibling   The first record we examined.
    465  */
    466 DECL_FORCE_INLINE(bool) rtLockValidatorDdMoreWorkLeft(PRTLOCKVALRECUNION pRec, uint32_t iEntry, PRTLOCKVALRECUNION pFirstSibling)
    467 {
    468     PRTLOCKVALRECUNION pSibling;
    469 
    470     switch (pRec->Core.u32Magic)
    471     {
    472         case RTLOCKVALRECEXCL_MAGIC:
    473             pSibling = pRec->Excl.pSibling;
    474             break;
    475 
    476         case RTLOCKVALRECSHRD_MAGIC:
    477             if (iEntry + 1 < pRec->Shared.cAllocated)
    478                 return true;
    479             pSibling = pRec->Excl.pSibling;
    480             break;
    481 
    482         default:
    483             return false;
    484     }
    485     return pSibling != NULL
    486         && pSibling != pFirstSibling;
    487 }
    488 
    489 
    490 /**
    491478 * Worker for rtLockValidatorDeadlockDetection that does the actual deadlock
    492479 * detection.
     
    519506         * Process the current record.
    520507         */
     508        RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
     509
    521510        /* Find the next relevant owner thread. */
    522511        PRTTHREADINT pNextThread;
     
    526515                Assert(iEntry == UINT32_MAX);
    527516                pNextThread = rtLockValidatorReadThreadHandle(&pRec->Excl.hThread);
    528                 if (    pNextThread
    529                     &&  pNextThread->u32Magic == RTTHREADINT_MAGIC
    530                     &&  !RTTHREAD_IS_SLEEPING(pNextThread->enmState)
    531                     &&  pNextThread != pThreadSelf)
    532                     pNextThread = NIL_RTTHREAD;
    533 
    534                 if (    pNextThread == NIL_RTTHREAD
    535                     &&  pRec->Excl.pSibling
    536                     &&  pRec->Excl.pSibling != pFirstSibling)
     517                if (    !pNextThread
     518                    ||  (   pNextThread != pThreadSelf
     519                         && (   pNextThread->u32Magic != RTTHREADINT_MAGIC
     520                             || !RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread)) )
     521                        )
     522                   )
    537523                {
    538524                    pRec = pRec->Excl.pSibling;
    539                     continue;
     525                    if (    pRec
     526                        &&  pRec != pFirstSibling)
     527                        continue;
     528                    pNextThread = NIL_RTTHREAD;
    540529                }
    541530                break;
     
    580569                            {
    581570                                if (   pNextThread->u32Magic == RTTHREADINT_MAGIC
    582                                     && (   RTTHREAD_IS_SLEEPING(pNextThread->enmState)
     571                                    && (   RTTHREAD_IS_SLEEPING(rtThreadGetState(pNextThread))
    583572                                        || pNextThread == pThreadSelf))
    584573                                    break;
     
    589578                            Assert(!pEntry || pEntry->Core.u32Magic == RTLOCKVALRECSHRDOWN_MAGIC_DEAD);
    590579                    }
    591                     if (pNextThread == NIL_RTTHREAD)
     580                    if (pNextThread != NIL_RTTHREAD)
    592581                        break;
    593582                }
    594583
    595584                /* Advance to the next sibling, if any. */
    596                 if (   pRec->Shared.pSibling != NULL
    597                     && pRec->Shared.pSibling != pFirstSibling)
     585                pRec = pRec->Shared.pSibling;
     586                if (   pRec != NULL
     587                    && pRec != pFirstSibling)
    598588                {
    599                     pRec = pRec->Shared.pSibling;
    600589                    iEntry = UINT32_MAX;
    601590                    continue;
    602591                }
     592                Assert(pNextThread == NIL_RTTHREAD);
    603593                break;
    604594
     
    673663                    return VINF_SUCCESS;
    674664                i--;
    675 
    676                 /* examine it. */
    677                 pRec            = pStack->a[i].pRec;
    678                 pFirstSibling   = pStack->a[i].pFirstSibling;
    679                 iEntry          = pStack->a[i].iEntry;
    680                 if (rtLockValidatorDdMoreWorkLeft(pRec, iEntry, pFirstSibling))
     665                pRec    = pStack->a[i].pRec;
     666                iEntry  = pStack->a[i].iEntry;
     667
     668                /* Examine it. */
     669                uint32_t u32Magic = pRec->Core.u32Magic;
     670                if (u32Magic == RTLOCKVALRECEXCL_MAGIC)
     671                    pRec = pRec->Excl.pSibling;
     672                else if (u32Magic == RTLOCKVALRECSHRD_MAGIC)
    681673                {
    682                     enmState    = pStack->a[i].enmState;
    683                     pThread     = pStack->a[i].pThread;
    684                     pStack->c   = i;
    685                     break;
     674                    if (iEntry + 1 < pRec->Shared.cAllocated)
     675                        break;  /* continue processing this record. */
     676                    pRec = pRec->Shared.pSibling;
    686677                }
     678                else
     679                {
     680                    Assert(   u32Magic == RTLOCKVALRECEXCL_MAGIC_DEAD
     681                           || u32Magic == RTLOCKVALRECSHRD_MAGIC_DEAD);
     682                    continue;
     683                }
     684
     685                /* Any next record to advance to? */
     686                if (   !pRec
     687                    || pRec == pStack->a[i].pFirstSibling)
     688                    continue;
     689                iEntry = UINT32_MAX;
     690                break;
    687691            }
     692
     693            /* Restore the rest of the state and update the stack. */
     694            pFirstSibling   = pStack->a[i].pFirstSibling;
     695            enmState        = pStack->a[i].enmState;
     696            pThread         = pStack->a[i].pThread;
     697            pStack->c       = i;
    688698        }
    689699        /* else: see if there is another thread to check for this lock. */
     
    888898                                        uint32_t uSubClass, const char *pszName, void *hLock)
    889899{
     900    RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
     901    RTLOCKVAL_ASSERT_PTR_ALIGN(hLock);
     902
    890903    pRec->Core.u32Magic = RTLOCKVALRECEXCL_MAGIC;
    891904    pRec->fEnabled      = RTLockValidatorIsEnabled();
     
    11871200                                          uint32_t uSubClass, const char *pszName, void *hLock)
    11881201{
     1202    RTLOCKVAL_ASSERT_PTR_ALIGN(pRec);
     1203    RTLOCKVAL_ASSERT_PTR_ALIGN(hLock);
     1204
    11891205    pRec->Core.u32Magic = RTLOCKVALRECSHRD_MAGIC;
    11901206    pRec->uSubClass     = uSubClass;
     
    17701786
    17711787
     1788RTDECL(void *) RTLockValidatorQueryBlocking(RTTHREAD hThread)
     1789{
     1790    void           *pvLock  = NULL;
     1791    PRTTHREADINT    pThread = rtThreadGet(hThread);
     1792    if (pThread)
     1793    {
     1794        RTTHREADSTATE enmState = rtThreadGetState(pThread);
     1795        if (RTTHREAD_IS_SLEEPING(enmState))
     1796        {
     1797            rtLockValidatorSerializeDetectionEnter();
     1798
     1799            enmState = rtThreadGetState(pThread);
     1800            if (RTTHREAD_IS_SLEEPING(enmState))
     1801            {
     1802                PRTLOCKVALRECUNION pRec = rtLockValidatorReadRecUnionPtr(&pThread->LockValidator.pRec);
     1803                if (pRec)
     1804                {
     1805                    switch (pRec->Core.u32Magic)
     1806                    {
     1807                        case RTLOCKVALRECEXCL_MAGIC:
     1808                            pvLock = pRec->Excl.hLock;
     1809                            break;
     1810
     1811                        case RTLOCKVALRECSHRDOWN_MAGIC:
     1812                            pRec = (PRTLOCKVALRECUNION)pRec->ShrdOwner.pSharedRec;
     1813                            if (!pRec || pRec->Core.u32Magic != RTLOCKVALRECSHRD_MAGIC)
     1814                                break;
     1815                        case RTLOCKVALRECSHRD_MAGIC:
     1816                            pvLock = pRec->Shared.hLock;
     1817                            break;
     1818                    }
     1819                    if (RTThreadGetState(pThread) != enmState)
     1820                        pvLock = NULL;
     1821                }
     1822            }
     1823
     1824            rtLockValidatorSerializeDetectionLeave();
     1825        }
     1826        rtThreadRelease(pThread);
     1827    }
     1828    return pvLock;
     1829}
     1830RT_EXPORT_SYMBOL(RTLockValidatorQueryBlocking);
     1831
     1832
    17721833RTDECL(bool) RTLockValidatorSetEnabled(bool fEnabled)
    17731834{
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