VirtualBox

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


Ignore:
Timestamp:
Jan 7, 2010 3:23:30 PM (15 years ago)
Author:
vboxsync
Message:

iprt,pdmcritsect: RTMSINTERVAL, RTLockValidatorClass* and some related renaming.

File:
1 edited

Legend:

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

    r25662 r25682  
    55
    66/*
    7  * Copyright (C) 2009 Sun Microsystems, Inc.
     7 * Copyright (C) 2009-2010 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    8888
    8989
     90/**
     91 * Reference to another class.
     92 */
     93typedef struct RTLOCKVALCLASSREF
     94{
     95    /** The class. */
     96    RTLOCKVALCLASS          hClass;
     97    /** The number of lookups of this class. */
     98    uint32_t volatile       cLookups;
     99    /** Indicates whether the entry was added automatically during order checking
     100     *  (true) or manually via the API (false). */
     101    bool                    fAutodidacticism;
     102    /** Reserved / explicit alignment padding. */
     103    bool                    afReserved[3];
     104} RTLOCKVALCLASSREF;
     105/** Pointer to a class reference. */
     106typedef RTLOCKVALCLASSREF *PRTLOCKVALCLASSREF;
     107
     108
     109/** Pointer to a chunk of class references. */
     110typedef struct RTLOCKVALCLASSREFCHUNK *PRTLOCKVALCLASSREFCHUNK;
     111/**
     112 * Chunk of class references.
     113 */
     114typedef struct RTLOCKVALCLASSREFCHUNK
     115{
     116    /** Array of refs. */
     117#if 0 /** @todo for testing alloction of new chunks. */
     118    RTLOCKVALCLASSREF       aRefs[ARCH_BITS == 32 ? 10 : 8];
     119#else
     120    RTLOCKVALCLASSREF       aRefs[2];
     121#endif
     122    /** Pointer to the next chunk. */
     123    PRTLOCKVALCLASSREFCHUNK volatile pNext;
     124} RTLOCKVALCLASSREFCHUNK;
     125
     126
     127/**
     128 * Lock class.
     129 */
     130typedef struct RTLOCKVALCLASSINT
     131{
     132    /** AVL node core. */
     133    AVLLU32NODECORE         Core;
     134    /** Magic value (RTLOCKVALCLASS_MAGIC). */
     135    uint32_t volatile       u32Magic;
     136    /** Reference counter.  See RTLOCKVALCLASS_MAX_REFS. */
     137    uint32_t volatile       cRefs;
     138    /** Whether the class is allowed to teach it self new locking order rules. */
     139    bool                    fAutodidact;
     140    /** Whether this class is in the tree. */
     141    bool                    fInTree;
     142    bool                    afReserved[2]; /**< Explicit padding */
     143    /** The minimum wait interval for which we do deadlock detection
     144     *  (milliseconds). */
     145    RTMSINTERVAL            cMsMinDeadlock;
     146    /** The minimum wait interval for which we do order checks (milliseconds). */
     147    RTMSINTERVAL            cMsMinOrder;
     148    /** More padding. */
     149    uint32_t                au32Reserved[ARCH_BITS == 32 ? 6 : 3];
     150    /** Classes that may be taken prior to this one.
     151     * This is a linked list where each node contains a chunk of locks so that we
     152     * reduce the number of allocations as well as localize the data. */
     153    RTLOCKVALCLASSREFCHUNK  PriorLocks;
     154    /** Hash table containing frequently encountered prior locks. */
     155    PRTLOCKVALCLASSREF      apPriorLocksHash[11];
     156#define RTLOCKVALCLASS_HASH_STATS
     157#ifdef RTLOCKVALCLASS_HASH_STATS
     158    /** Hash hits. */
     159    uint32_t volatile       cHashHits;
     160    /** Hash misses. */
     161    uint32_t volatile       cHashMisses;
     162#endif
     163    /** Where this class was created.
     164     *  This is mainly used for finding automatically created lock classes.
     165     *  @remarks The strings are stored after this structure so we won't crash
     166     *           if the class lives longer than the module (dll/so/dylib) that
     167     *           spawned it. */
     168    RTLOCKVALSRCPOS         CreatePos;
     169} RTLOCKVALCLASSINT;
     170AssertCompileSize(AVLLU32NODECORE, ARCH_BITS == 32 ? 20 : 32);
     171AssertCompileMemberOffset(RTLOCKVALCLASSINT, PriorLocks, 64);
     172
     173
    90174/*******************************************************************************
    91175*   Defined Constants And Macros                                               *
     
    94178 * Only used when fighting bugs. */
    95179#if 1
    96 # define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   \
     180# define RTLOCKVAL_ASSERT_PTR_ALIGN(p) \
    97181    AssertMsg(!((uintptr_t)(p) & (sizeof(uintptr_t) - 1)), ("%p\n", (p)));
    98182#else
    99183# define RTLOCKVAL_ASSERT_PTR_ALIGN(p)   do { } while (0)
    100184#endif
     185
     186/** Hashes the class handle (pointer) into an apPriorLocksHash index. */
     187#define RTLOCKVALCLASS_HASH(hClass) \
     188    (   (uintptr_t)(hClass) \
     189      % (  RT_SIZEOFMEMB(RTLOCKVALCLASSINT, apPriorLocksHash) \
     190         / sizeof(PRTLOCKVALCLASSREF)) )
     191
     192/** The max value for RTLOCKVALCLASSINT::cRefs. */
     193#define RTLOCKVALCLASS_MAX_REFS             UINT32_C(0xffff0000)
     194/** The max value for RTLOCKVALCLASSREF::cLookups. */
     195#define RTLOCKVALCLASSREF_MAX_LOOKUPS       UINT32_C(0xfffe0000)
     196/** The absolute max value for RTLOCKVALCLASSREF::cLookups at which it will
     197 *  be set back to RTLOCKVALCLASSREF_MAX_LOOKUPS. */
     198#define RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX   UINT32_C(0xffff0000)
    101199
    102200
     
    129227static bool volatile    g_fLockValidatorMayPanic = false;
    130228#endif
     229/** Serializing class tree insert and lookups. */
     230static RTSEMRW          g_hLockValClassTreeRWLock = NIL_RTSEMRW;
     231/** Class tree. */
     232static PAVLLU32NODECORE g_LockValClassTree = NULL;
     233/** Critical section serializing the teaching new rules to the classes. */
     234static RTCRITSECT       g_LockValClassTeachCS;
     235
     236
     237/*******************************************************************************
     238*   Internal Functions                                                         *
     239*******************************************************************************/
     240static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass);
     241
     242
     243/**
     244 * Lazy initialization of the lock validator globals.
     245 */
     246static void rtLockValidatorLazyInit(void)
     247{
     248    static uint32_t volatile s_fInitializing = false;
     249    if (ASMAtomicCmpXchgU32(&s_fInitializing, true, false))
     250    {
     251        if (!RTCritSectIsInitialized(&g_LockValClassTeachCS))
     252            RTCritSectInit(&g_LockValClassTeachCS);
     253
     254        if (g_hLockValClassTreeRWLock == NIL_RTSEMRW)
     255        {
     256            RTSEMRW hSemRW;
     257            int rc = RTSemRWCreate(&hSemRW);
     258            if (RT_SUCCESS(rc))
     259                ASMAtomicWriteHandle(&g_hLockValClassTreeRWLock, hSemRW);
     260        }
     261
     262        if (g_hLockValidatorXRoads == NIL_RTSEMXROADS)
     263        {
     264            RTSEMXROADS hXRoads;
     265            int rc = RTSemXRoadsCreate(&hXRoads);
     266            if (RT_SUCCESS(rc))
     267                ASMAtomicWriteHandle(&g_hLockValidatorXRoads, hXRoads);
     268        }
     269
     270        /** @todo register some cleanup callback if we care. */
     271
     272        ASMAtomicWriteU32(&s_fInitializing, false);
     273    }
     274    else
     275        RTThreadYield();
     276}
     277
    131278
    132279
     
    321468 * @param   pSrc                The source.  Can be NULL.
    322469 */
    323 DECL_FORCE_INLINE(void) rtLockValidatorCopySrcPos(PRTLOCKVALSRCPOS pDst, PCRTLOCKVALSRCPOS pSrc)
     470DECL_FORCE_INLINE(void) rtLockValidatorSrcPosCopy(PRTLOCKVALSRCPOS pDst, PCRTLOCKVALSRCPOS pSrc)
    324471{
    325472    if (pSrc)
     
    345492 * @param   pSrcPos             The source position record.
    346493 */
    347 DECL_FORCE_INLINE(void) rtLockValidatorInitSrcPos(PRTLOCKVALSRCPOS pSrcPos)
     494DECL_FORCE_INLINE(void) rtLockValidatorSrcPosInit(PRTLOCKVALSRCPOS pSrcPos)
    348495{
    349496    pSrcPos->pszFile        = NULL;
     
    357504
    358505
     506/* sdbm:
     507   This algorithm was created for sdbm (a public-domain reimplementation of
     508   ndbm) database library. it was found to do well in scrambling bits,
     509   causing better distribution of the keys and fewer splits. it also happens
     510   to be a good general hashing function with good distribution. the actual
     511   function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below
     512   is the faster version used in gawk. [there is even a faster, duff-device
     513   version] the magic constant 65599 was picked out of thin air while
     514   experimenting with different constants, and turns out to be a prime.
     515   this is one of the algorithms used in berkeley db (see sleepycat) and
     516   elsewhere. */
     517DECL_FORCE_INLINE(uint32_t) sdbm(const char *str, uint32_t hash)
     518{
     519    uint8_t *pu8 = (uint8_t *)str;
     520    int c;
     521
     522    while ((c = *pu8++))
     523        hash = c + (hash << 6) + (hash << 16) - hash;
     524
     525    return hash;
     526}
     527
     528
     529/**
     530 * Hashes the specified source position.
     531 *
     532 * @returns Hash.
     533 * @param   pSrcPos             The source position record.
     534 */
     535static uint32_t rtLockValidatorSrcPosHash(PCRTLOCKVALSRCPOS pSrcPos)
     536{
     537    uint32_t uHash;
     538    if (   (   pSrcPos->pszFile
     539            || pSrcPos->pszFunction)
     540        && pSrcPos->uLine != 0)
     541    {
     542        uHash = 0;
     543        if (pSrcPos->pszFile)
     544            uHash = sdbm(pSrcPos->pszFile, uHash);
     545        if (pSrcPos->pszFunction)
     546            uHash = sdbm(pSrcPos->pszFunction, uHash);
     547        uHash += pSrcPos->uLine;
     548    }
     549    else
     550    {
     551        Assert(pSrcPos->uId);
     552        uHash = (uint32_t)pSrcPos->uId;
     553    }
     554
     555    return uHash;
     556}
     557
     558
     559/**
     560 * Compares two source positions.
     561 *
     562 * @returns 0 if equal, < 0 if pSrcPos1 is smaller than pSrcPos2, > 0 if
     563 *          otherwise.
     564 * @param   pSrcPos1            The first source position.
     565 * @param   pSrcPos2            The second source position.
     566 */
     567static int rtLockValidatorSrcPosCompare(PCRTLOCKVALSRCPOS pSrcPos1, PCRTLOCKVALSRCPOS pSrcPos2)
     568{
     569    if (pSrcPos1->uLine != pSrcPos2->uLine)
     570        return pSrcPos1->uLine < pSrcPos2->uLine ? -1 : 1;
     571
     572    int iDiff = RTStrCmp(pSrcPos1->pszFile, pSrcPos2->pszFile);
     573    if (iDiff != 0)
     574        return iDiff;
     575
     576    iDiff = RTStrCmp(pSrcPos1->pszFunction, pSrcPos2->pszFunction);
     577    if (iDiff != 0)
     578        return iDiff;
     579
     580    if (pSrcPos1->uId != pSrcPos2->uId)
     581        return pSrcPos1->uId < pSrcPos2->uId ? -1 : 1;
     582    return 0;
     583}
     584
     585
     586
    359587/**
    360588 * Serializes destruction of RTLOCKVALREC* and RTTHREADINT structures.
     
    416644    Assert(pPerThread->cReadLocks == 0);
    417645    Assert(pPerThread->fInValidator == false);
     646}
     647
     648
     649RTDECL(int) RTLockValidatorClassCreateEx(PRTLOCKVALCLASS phClass, PCRTLOCKVALSRCPOS pSrcPos,
     650                                         bool fAutodidact, RTMSINTERVAL cMsMinDeadlock, RTMSINTERVAL cMsMinOrder)
     651{
     652    Assert(cMsMinDeadlock >= 1);
     653    Assert(cMsMinOrder    >= 1);
     654    AssertPtr(pSrcPos);
     655
     656    size_t const       cbFile   = pSrcPos->pszFile ? strlen(pSrcPos->pszFile) + 1 : 0;
     657    size_t const     cbFunction = pSrcPos->pszFile ? strlen(pSrcPos->pszFunction) + 1 : 0;
     658    RTLOCKVALCLASSINT *pThis    = (RTLOCKVALCLASSINT *)RTMemAlloc(sizeof(*pThis) + cbFile + cbFunction);
     659    if (!pThis)
     660        return VERR_NO_MEMORY;
     661
     662    pThis->Core.Key             = rtLockValidatorSrcPosHash(pSrcPos);
     663    pThis->Core.uchHeight       = 0;
     664    pThis->Core.pLeft           = NULL;
     665    pThis->Core.pRight          = NULL;
     666    pThis->Core.pList           = NULL;
     667    pThis->u32Magic             = RTLOCKVALCLASS_MAGIC;
     668    pThis->cRefs                = 1;
     669    pThis->fAutodidact          = fAutodidact;
     670    pThis->fInTree              = false;
     671    for (unsigned i = 0; i < RT_ELEMENTS(pThis->afReserved); i++)
     672        pThis->afReserved[i]    = false;
     673    pThis->cMsMinDeadlock       = cMsMinDeadlock;
     674    pThis->cMsMinOrder          = cMsMinOrder;
     675    for (unsigned i = 0; i < RT_ELEMENTS(pThis->au32Reserved); i++)
     676        pThis->au32Reserved[i]  = 0;
     677    for (unsigned i = 0; i < RT_ELEMENTS(pThis->au32Reserved); i++)
     678    {
     679        pThis->PriorLocks.aRefs[i].hClass           = NIL_RTLOCKVALCLASS;
     680        pThis->PriorLocks.aRefs[i].cLookups         = 0;
     681        pThis->PriorLocks.aRefs[i].fAutodidacticism = false;
     682        pThis->PriorLocks.aRefs[i].afReserved[0]    = false;
     683        pThis->PriorLocks.aRefs[i].afReserved[1]    = false;
     684        pThis->PriorLocks.aRefs[i].afReserved[2]    = false;
     685    }
     686    pThis->PriorLocks.pNext     = NULL;
     687    for (unsigned i = 0; i < RT_ELEMENTS(pThis->apPriorLocksHash); i++)
     688        pThis->apPriorLocksHash[i] = NULL;
     689    rtLockValidatorSrcPosCopy(&pThis->CreatePos, pSrcPos);
     690    char *pszDst = (char *)(pThis + 1);
     691    pThis->CreatePos.pszFile    = pSrcPos->pszFile     ? (char *)memcpy(pszDst, pSrcPos->pszFile,     cbFile)     : NULL;
     692    pszDst += cbFile;
     693    pThis->CreatePos.pszFunction= pSrcPos->pszFunction ? (char *)memcpy(pszDst, pSrcPos->pszFunction, cbFunction) : NULL;
     694    Assert(rtLockValidatorSrcPosHash(&pThis->CreatePos) == pThis->Core.Key);
     695
     696    *phClass = pThis;
     697    return VINF_SUCCESS;
     698}
     699
     700
     701RTDECL(int) RTLockValidatorClassCreate(PRTLOCKVALCLASS phClass, bool fAutodidact, RT_SRC_POS_DECL)
     702{
     703    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_POS_NO_ID();
     704    return RTLockValidatorClassCreateEx(phClass, &SrcPos, fAutodidact,
     705                                        1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
     706}
     707
     708
     709/**
     710 * Internal class retainer.
     711 * @returns The new reference count.
     712 * @param   pClass              The class.
     713 */
     714DECL_FORCE_INLINE(uint32_t) rtLockValidatorClassRetain(RTLOCKVALCLASSINT *pClass)
     715{
     716    uint32_t cRefs = ASMAtomicIncU32(&pClass->cRefs);
     717    if (cRefs > RTLOCKVALCLASS_MAX_REFS)
     718        ASMAtomicWriteU32(&pClass->cRefs, RTLOCKVALCLASS_MAX_REFS);
     719    return cRefs;
     720}
     721
     722
     723/**
     724 * Validates and retains a lock validator class.
     725 *
     726 * @returns @a hClass on success, NIL_RTLOCKVALCLASS on failure.
     727 * @param   hClass              The class handle.  NIL_RTLOCKVALCLASS is ok.
     728 */
     729DECL_FORCE_INLINE(RTLOCKVALCLASS) rtLockValidatorClassValidateAndRetain(RTLOCKVALCLASS hClass)
     730{
     731    if (hClass == NIL_RTLOCKVALCLASS)
     732        return hClass;
     733    AssertPtrReturn(hClass, NIL_RTLOCKVALCLASS);
     734    AssertReturn(hClass->u32Magic == RTLOCKVALCLASS_MAGIC, NIL_RTLOCKVALCLASS);
     735    rtLockValidatorClassRetain(hClass);
     736    return hClass;
     737}
     738
     739
     740/**
     741 * Internal class releaser.
     742 * @returns The new reference count.
     743 * @param   pClass              The class.
     744 */
     745DECL_FORCE_INLINE(uint32_t) rtLockValidatorClassRelease(RTLOCKVALCLASSINT *pClass)
     746{
     747    uint32_t cRefs = ASMAtomicDecU32(&pClass->cRefs);
     748    if (cRefs + 1 == RTLOCKVALCLASS_MAX_REFS)
     749        ASMAtomicWriteU32(&pClass->cRefs, RTLOCKVALCLASS_MAX_REFS);
     750    else if (!cRefs)
     751        rtLockValidatorClassDestroy(pClass);
     752    return cRefs;
     753}
     754
     755
     756/**
     757 * Destroys a class once there are not more references to it.
     758 *
     759 * @param   Class               The class.
     760 */
     761static void rtLockValidatorClassDestroy(RTLOCKVALCLASSINT *pClass)
     762{
     763    AssertReturnVoid(pClass->fInTree);
     764    ASMAtomicWriteU32(&pClass->u32Magic, RTLOCKVALCLASS_MAGIC_DEAD);
     765
     766    PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks;
     767    while (pChunk)
     768    {
     769        for (uint32_t i = 0; i < RT_ELEMENTS(pChunk->aRefs); i++)
     770        {
     771            RTLOCKVALCLASSINT *pClass2 = pChunk->aRefs[i].hClass;
     772            if (pClass2 != NIL_RTLOCKVALCLASS)
     773            {
     774                pChunk->aRefs[i].hClass = NIL_RTLOCKVALCLASS;
     775                rtLockValidatorClassRelease(pClass2);
     776            }
     777        }
     778
     779        PRTLOCKVALCLASSREFCHUNK pNext = pChunk->pNext;
     780        pChunk->pNext = NULL;
     781        if (pChunk != &pClass->PriorLocks)
     782            RTMemFree(pChunk);
     783        pNext = pChunk;
     784    }
     785
     786    RTMemFree(pClass);
     787}
     788
     789
     790RTDECL(RTLOCKVALCLASS) RTLockValidatorClassFindForSrcPos(PRTLOCKVALSRCPOS pSrcPos)
     791{
     792    if (g_hLockValClassTreeRWLock == NIL_RTSEMRW)
     793        rtLockValidatorLazyInit();
     794    int rcLock = RTSemRWRequestRead(g_hLockValClassTreeRWLock, RT_INDEFINITE_WAIT);
     795
     796    uint32_t uSrcPosHash = rtLockValidatorSrcPosHash(pSrcPos);
     797    RTLOCKVALCLASSINT *pClass = (RTLOCKVALCLASSINT *)RTAvllU32Get(&g_LockValClassTree, uSrcPosHash);
     798    while (pClass)
     799    {
     800        if (rtLockValidatorSrcPosCompare(&pClass->CreatePos, pSrcPos) == 0)
     801        {
     802            rtLockValidatorClassRetain(pClass);
     803            break;
     804        }
     805        pClass = (RTLOCKVALCLASSINT *)pClass->Core.pList;
     806    }
     807
     808    if (RT_SUCCESS(rcLock))
     809        RTSemRWReleaseRead(g_hLockValClassTreeRWLock);
     810    return pClass;
     811}
     812
     813
     814RTDECL(RTLOCKVALCLASS) RTLockValidatorClassForSrcPos(RT_SRC_POS_DECL)
     815{
     816    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_POS_NO_ID();
     817    RTLOCKVALCLASS  hClass = RTLockValidatorClassFindForSrcPos(&SrcPos);
     818    if (hClass == NIL_RTLOCKVALCLASS)
     819    {
     820        /*
     821         * Create a new class and insert it into the tree.
     822         */
     823        int rc = RTLockValidatorClassCreateEx(&hClass, &SrcPos, true /*fAutodidact*/,
     824                                              1 /*cMsMinDeadlock*/, 1 /*cMsMinOrder*/);
     825        if (RT_SUCCESS(rc))
     826        {
     827            if (g_hLockValClassTreeRWLock == NIL_RTSEMRW)
     828                rtLockValidatorLazyInit();
     829            int rcLock = RTSemRWRequestWrite(g_hLockValClassTreeRWLock, RT_INDEFINITE_WAIT);
     830
     831            Assert(!hClass->fInTree);
     832            hClass->fInTree = RTAvllU32Insert(&g_LockValClassTree, &hClass->Core);
     833            Assert(hClass->fInTree);
     834
     835            if (RT_SUCCESS(rcLock))
     836                RTSemRWReleaseWrite(g_hLockValClassTreeRWLock);
     837            return hClass;
     838        }
     839    }
     840    return hClass;
     841}
     842
     843
     844RTDECL(uint32_t) RTLockValidatorClassRetain(RTLOCKVALCLASS hClass)
     845{
     846    RTLOCKVALCLASSINT *pClass = hClass;
     847    AssertPtrReturn(pClass, UINT32_MAX);
     848    AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, UINT32_MAX);
     849    return rtLockValidatorClassRetain(pClass);
     850}
     851
     852
     853RTDECL(uint32_t) RTLockValidatorClassRelease(RTLOCKVALCLASS hClass)
     854{
     855    RTLOCKVALCLASSINT *pClass = hClass;
     856    AssertPtrReturn(pClass, UINT32_MAX);
     857    AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, UINT32_MAX);
     858    return rtLockValidatorClassRelease(pClass);
     859}
     860
     861
     862/**
     863 * Worker for rtLockValidatorClassIsPriorClass that does a linear search thru
     864 * all the chunks for @a pPriorClass.
     865 *
     866 * @returns true / false.
     867 * @param   pClass              The class to search.
     868 * @param   pPriorClass         The class to search for.
     869 */
     870static bool rtLockValidatorClassIsPriorClassByLinearSearch(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass)
     871{
     872    for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; pChunk; pChunk = pChunk->pNext)
     873        for (uint32_t i = 0; i < RT_ELEMENTS(pChunk->aRefs); i++)
     874        {
     875            if (pChunk->aRefs[i].hClass == pPriorClass)
     876            {
     877                uint32_t cLookups = ASMAtomicIncU32(&pChunk->aRefs[i].cLookups);
     878                if (RT_UNLIKELY(cLookups >= RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX))
     879                {
     880                    ASMAtomicWriteU32(&pChunk->aRefs[i].cLookups, RTLOCKVALCLASSREF_MAX_LOOKUPS);
     881                    cLookups = RTLOCKVALCLASSREF_MAX_LOOKUPS;
     882                }
     883
     884                /* update the hash table entry. */
     885                PRTLOCKVALCLASSREF *ppHashEntry = &pClass->apPriorLocksHash[RTLOCKVALCLASS_HASH(pPriorClass)];
     886                if (    !(*ppHashEntry)
     887                    ||  (*ppHashEntry)->cLookups + 128 < cLookups)
     888                    ASMAtomicWritePtr((void * volatile *)ppHashEntry, &pChunk->aRefs[i]);
     889
     890#ifdef RTLOCKVALCLASS_HASH_STATS
     891                ASMAtomicIncU32(&pClass->cHashMisses);
     892#endif
     893                return true;
     894            }
     895        }
     896
     897    return false;
     898}
     899
     900
     901/**
     902 * Checks if @a pPriorClass is a known prior class.
     903 *
     904 * @returns true / false.
     905 * @param   pClass              The class to search.
     906 * @param   pPriorClass         The class to search for.
     907 */
     908DECL_FORCE_INLINE(bool) rtLockValidatorClassIsPriorClass(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass)
     909{
     910    /*
     911     * Hash lookup here.
     912     */
     913    PRTLOCKVALCLASSREF pRef = pClass->apPriorLocksHash[RTLOCKVALCLASS_HASH(pPriorClass)];
     914    if (    pRef
     915        &&  pRef->hClass == pPriorClass)
     916    {
     917        uint32_t cLookups = ASMAtomicIncU32(&pRef->cLookups);
     918        if (RT_UNLIKELY(cLookups >= RTLOCKVALCLASSREF_MAX_LOOKUPS_FIX))
     919            ASMAtomicWriteU32(&pRef->cLookups, RTLOCKVALCLASSREF_MAX_LOOKUPS);
     920#ifdef RTLOCKVALCLASS_HASH_STATS
     921        ASMAtomicIncU32(&pClass->cHashHits);
     922#endif
     923        return true;
     924    }
     925
     926    return rtLockValidatorClassIsPriorClassByLinearSearch(pClass, pPriorClass);
     927}
     928
     929
     930/**
     931 * Adds a class to the prior list.
     932 *
     933 * @returns VINF_SUCCESS, VERR_NO_MEMORY or VERR_SEM_LV_WRONG_ORDER.
     934 * @param   pClass              The class to work on.
     935 * @param   pPriorClass         The class to add.
     936 * @param   fAutodidacticism    Whether we're teaching ourselfs (true) or
     937 *                              somebody is teaching us via the API (false).
     938 */
     939static int rtLockValidatorClassAddPriorClass(RTLOCKVALCLASSINT *pClass, RTLOCKVALCLASSINT *pPriorClass, bool fAutodidacticism)
     940{
     941    if (!RTCritSectIsInitialized(&g_LockValClassTeachCS))
     942        rtLockValidatorLazyInit();
     943    int rcLock = RTCritSectEnter(&g_LockValClassTeachCS);
     944
     945    /*
     946     * Check that there are no conflict (no assert since we might race each other).
     947     */
     948    int rc = VERR_INTERNAL_ERROR_5;
     949    if (!rtLockValidatorClassIsPriorClass(pPriorClass, pClass))
     950    {
     951        if (!rtLockValidatorClassIsPriorClass(pClass, pPriorClass))
     952        {
     953            /*
     954             * Scan the table for a free entry, allocating a new chunk if necessary.
     955             */
     956            for (PRTLOCKVALCLASSREFCHUNK pChunk = &pClass->PriorLocks; ; pChunk = pChunk->pNext)
     957            {
     958                bool fDone = false;
     959                for (uint32_t i = 0; i < RT_ELEMENTS(pChunk->aRefs); i++)
     960                {
     961                    ASMAtomicCmpXchgHandle(&pChunk->aRefs[i].hClass, pPriorClass, NIL_RTLOCKVALCLASS, fDone);
     962                    if (fDone)
     963                    {
     964                        pChunk->aRefs[i].fAutodidacticism = fAutodidacticism;
     965                        rc = VINF_SUCCESS;
     966                        break;
     967                    }
     968                }
     969                if (fDone)
     970                    break;
     971
     972                /* If no more chunks, allocate a new one and insert the class before linking it. */
     973                if (!pChunk->pNext)
     974                {
     975                    PRTLOCKVALCLASSREFCHUNK pNew = (PRTLOCKVALCLASSREFCHUNK)RTMemAlloc(sizeof(*pNew));
     976                    if (!pNew)
     977                    {
     978                        rc = VERR_NO_MEMORY;
     979                        break;
     980                    }
     981                    pNew->pNext = NULL;
     982                    for (uint32_t i = 0; i < RT_ELEMENTS(pNew->aRefs); i++)
     983                    {
     984                        pNew->aRefs[i].hClass           = NIL_RTLOCKVALCLASS;
     985                        pNew->aRefs[i].cLookups         = 0;
     986                        pNew->aRefs[i].fAutodidacticism = false;
     987                        pNew->aRefs[i].afReserved[0]    = false;
     988                        pNew->aRefs[i].afReserved[1]    = false;
     989                        pNew->aRefs[i].afReserved[2]    = false;
     990                    }
     991
     992                    pNew->aRefs[0].hClass           = pPriorClass;
     993                    pNew->aRefs[0].fAutodidacticism = fAutodidacticism;
     994
     995                    ASMAtomicWritePtr((void * volatile *)&pChunk->pNext, pNew);
     996                    rc = VINF_SUCCESS;
     997                    break;
     998                }
     999            } /* chunk loop */
     1000        }
     1001        else
     1002            rc = VINF_SUCCESS;
     1003    }
     1004    else
     1005        rc = VERR_SEM_LV_WRONG_ORDER;
     1006
     1007    if (RT_SUCCESS(rcLock))
     1008        RTCritSectLeave(&g_LockValClassTeachCS);
     1009    return rc;
     1010}
     1011
     1012
     1013RTDECL(int) RTLockValidatorClassAddPriorClass(RTLOCKVALCLASS hClass, RTLOCKVALCLASS hPriorClass)
     1014{
     1015    RTLOCKVALCLASSINT *pClass = hClass;
     1016    AssertPtrReturn(pClass, VERR_INVALID_HANDLE);
     1017    AssertReturn(pClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE);
     1018
     1019    RTLOCKVALCLASSINT *pPriorClass = hPriorClass;
     1020    AssertPtrReturn(pPriorClass, VERR_INVALID_HANDLE);
     1021    AssertReturn(pPriorClass->u32Magic == RTLOCKVALCLASS_MAGIC, VERR_INVALID_HANDLE);
     1022
     1023    return rtLockValidatorClassAddPriorClass(pClass, pPriorClass, false /*fAutodidacticism*/);
    4181024}
    4191025
     
    4571063    return true;
    4581064}
    459 
    460 
    4611065
    4621066
     
    9601564
    9611565
    962 
    963 
    964 RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec, RTLOCKVALIDATORCLASS hClass,
     1566RTDECL(void) RTLockValidatorRecExclInit(PRTLOCKVALRECEXCL pRec, RTLOCKVALCLASS hClass,
    9651567                                        uint32_t uSubClass, const char *pszName, void *hLock)
    9661568{
     
    9731575    pRec->afReserved[1] = 0;
    9741576    pRec->afReserved[2] = 0;
    975     rtLockValidatorInitSrcPos(&pRec->SrcPos);
     1577    rtLockValidatorSrcPosInit(&pRec->SrcPos);
    9761578    pRec->hThread       = NIL_RTTHREAD;
    9771579    pRec->pDown         = NULL;
    978     pRec->hClass        = hClass;
     1580    pRec->hClass        = rtLockValidatorClassValidateAndRetain(hClass);
    9791581    pRec->uSubClass     = uSubClass;
    9801582    pRec->cRecursion    = 0;
     
    9831585    pRec->pSibling      = NULL;
    9841586
    985     /* Lazily initialize the crossroads semaphore. */
    986     static uint32_t volatile s_fInitializing = false;
    987     if (RT_UNLIKELY(    g_hLockValidatorXRoads == NIL_RTSEMXROADS
    988                     &&  ASMAtomicCmpXchgU32(&s_fInitializing, true, false)))
    989     {
    990         RTSEMXROADS hXRoads;
    991         int rc = RTSemXRoadsCreate(&hXRoads);
    992         if (RT_SUCCESS(rc))
    993             ASMAtomicWriteHandle(&g_hLockValidatorXRoads, hXRoads);
    994         ASMAtomicWriteU32(&s_fInitializing, false);
    995     }
    996 }
    997 
    998 
    999 RTDECL(int)  RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALIDATORCLASS hClass,
     1587    /* Lazy initialization. */
     1588    if (RT_UNLIKELY(g_hLockValidatorXRoads == NIL_RTSEMXROADS))
     1589        rtLockValidatorLazyInit();
     1590}
     1591
     1592
     1593RTDECL(int)  RTLockValidatorRecExclCreate(PRTLOCKVALRECEXCL *ppRec, RTLOCKVALCLASS hClass,
    10001594                                          uint32_t uSubClass, const char *pszName, void *pvLock)
    10011595{
     
    10191613    ASMAtomicWriteU32(&pRec->Core.u32Magic, RTLOCKVALRECEXCL_MAGIC_DEAD);
    10201614    ASMAtomicWriteHandle(&pRec->hThread, NIL_RTTHREAD);
    1021     ASMAtomicWriteHandle(&pRec->hClass, NIL_RTLOCKVALIDATORCLASS);
     1615    ASMAtomicWriteHandle(&pRec->hClass, NIL_RTLOCKVALCLASS);
    10221616    if (pRec->pSibling)
    10231617        rtLockValidatorUnlinkAllSiblings(&pRec->Core);
     
    10651659         * Update the record.
    10661660         */
    1067         rtLockValidatorCopySrcPos(&pRec->SrcPos, pSrcPos);
     1661        rtLockValidatorSrcPosCopy(&pRec->SrcPos, pSrcPos);
    10681662        ASMAtomicUoWriteU32(&pRec->cRecursion, 1);
    10691663        ASMAtomicWriteHandle(&pRec->hThread, hThreadSelf);
     
    12321826     */
    12331827    rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, pRecU);
    1234     rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
     1828    rtLockValidatorSrcPosCopy(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
    12351829    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
    12361830    pThreadSelf->LockValidator.enmRecState = enmSleepState;
     
    12841878
    12851879
    1286 RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec, RTLOCKVALIDATORCLASS hClass, uint32_t uSubClass,
     1880RTDECL(void) RTLockValidatorRecSharedInit(PRTLOCKVALRECSHRD pRec, RTLOCKVALCLASS hClass, uint32_t uSubClass,
    12871881                                          const char *pszName, void *hLock, bool fSignaller)
    12881882{
     
    12921886    pRec->Core.u32Magic = RTLOCKVALRECSHRD_MAGIC;
    12931887    pRec->uSubClass     = uSubClass;
    1294     pRec->hClass        = hClass;
     1888    pRec->hClass        = rtLockValidatorClassValidateAndRetain(hClass);
    12951889    pRec->hLock         = hLock;
    12961890    pRec->pszName       = pszName;
     
    13311925
    13321926    ASMAtomicWriteU32(&pRec->Core.u32Magic, RTLOCKVALRECSHRD_MAGIC_DEAD);
    1333     ASMAtomicUoWriteHandle(&pRec->hClass, NIL_RTLOCKVALIDATORCLASS);
     1927    ASMAtomicUoWriteHandle(&pRec->hClass, NIL_RTLOCKVALCLASS);
    13341928    if (pRec->papOwners)
    13351929    {
     
    14372031     */
    14382032    rtLockValidatorWriteRecUnionPtr(&pThreadSelf->LockValidator.pRec, pRecU);
    1439     rtLockValidatorCopySrcPos(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
     2033    rtLockValidatorSrcPosCopy(&pThreadSelf->LockValidator.SrcPos, pSrcPos);
    14402034    ASMAtomicWriteBool(&pThreadSelf->LockValidator.fInValidator, true);
    14412035    pThreadSelf->LockValidator.enmRecState = enmSleepState;
     
    15362130        pEntry->SrcPos      = *pSrcPos;
    15372131    else
    1538         rtLockValidatorInitSrcPos(&pEntry->SrcPos);
     2132        rtLockValidatorSrcPosInit(&pEntry->SrcPos);
    15392133    return pEntry;
    15402134}
     
    18802474     * Check the release order.
    18812475     */
    1882     if (pRec->hClass != NIL_RTLOCKVALIDATORCLASS)
     2476    if (pRec->hClass != NIL_RTLOCKVALCLASS)
    18832477    {
    18842478        /** @todo order validation */
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