VirtualBox

儲存庫 vbox 的更動 37203


忽略:
時間撮記:
2011-5-24 下午04:12:43 (14 年 以前)
作者:
vboxsync
訊息:

GMMR0: Try reduce chunk lock contention.

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/VMM/VMMR0/GMMR0.cpp

    r37195 r37203  
    400400    /** The mapping lock this chunk is using using.  UINT16_MAX if nobody is
    401401     *  mapping or freeing anything.  (Giant mtx.) */
    402     uint8_t volatile    iMemLock;
     402    uint8_t volatile    iChunkMtx;
    403403    /** Flags field reserved for future use (like eliminating enmType).
    404404     *  (Giant mtx.) */
     
    571571    /** Chunk locks for reducing lock contention without having to allocate
    572572     * one lock per chunk. */
    573     RTSEMFASTMUTEX      ahChunkMtx[64];
     573    struct
     574    {
     575        /** The mutex */
     576        RTSEMFASTMUTEX      hMtx;
     577        /** The number of threads currently using this mutex. */
     578        uint32_t volatile   cUsers;
     579    } aChunkMtx[64];
    574580} GMM;
    575581/** Pointer to the GMM instance. */
     
    730736        {
    731737            unsigned iMtx;
    732             for (iMtx = 0; iMtx < RT_ELEMENTS(pGMM->ahChunkMtx); iMtx++)
     738            for (iMtx = 0; iMtx < RT_ELEMENTS(pGMM->aChunkMtx); iMtx++)
    733739            {
    734                 rc = RTSemFastMutexCreate(&pGMM->ahChunkMtx[iMtx]);
     740                rc = RTSemFastMutexCreate(&pGMM->aChunkMtx[iMtx].hMtx);
    735741                if (RT_FAILURE(rc))
    736742                    break;
     
    783789             */
    784790            while (iMtx-- > 0)
    785                 RTSemFastMutexDestroy(pGMM->ahChunkMtx[iMtx]);
     791                RTSemFastMutexDestroy(pGMM->aChunkMtx[iMtx].hMtx);
    786792        }
    787793        RTSemFastMutexDestroy(pGMM->hMtx);
     
    829835
    830836    /* Destroy the chunk locks. */
    831     for (unsigned iMtx = 0; iMtx++ < RT_ELEMENTS(pGMM->ahChunkMtx); iMtx++)
    832     {
    833         RTSemFastMutexDestroy(pGMM->ahChunkMtx[iMtx]);
    834         pGMM->ahChunkMtx[iMtx] = NIL_RTSEMFASTMUTEX;
     837    for (unsigned iMtx = 0; iMtx++ < RT_ELEMENTS(pGMM->aChunkMtx); iMtx++)
     838    {
     839        Assert(pGMM->aChunkMtx[iMtx].cUsers == 0);
     840        RTSemFastMutexDestroy(pGMM->aChunkMtx[iMtx].hMtx);
     841        pGMM->aChunkMtx[iMtx].hMtx = NIL_RTSEMFASTMUTEX;
    835842    }
    836843
     
    9931000{
    9941001    Assert(fFlags > GMMR0CHUNK_MTX_INVALID && fFlags < GMMR0CHUNK_MTX_END);
     1002    Assert(pGMM->hMtxOwner == RTThreadNativeSelf());
     1003
    9951004    pMtxState->pGMM   = pGMM;
    9961005    pMtxState->fFlags = (uint8_t)fFlags;
    9971006
    9981007    /*
    999      * Get the lock index.
     1008     * Get the lock index and reference the lock.
    10001009     */
    10011010    Assert(pGMM->hMtxOwner == RTThreadNativeSelf());
    1002     uint32_t iChunkMtx = pChunk->iMemLock;
     1011    uint32_t iChunkMtx = pChunk->iChunkMtx;
    10031012    if (iChunkMtx == UINT8_MAX)
    10041013    {
    1005         /** @todo skip mutexes that are currently owned.  */
    10061014        iChunkMtx = pGMM->iNextChunkMtx++;
    1007         iChunkMtx %= RT_ELEMENTS(pGMM->ahChunkMtx);
    1008         pChunk->iMemLock = iChunkMtx;
    1009     }
    1010     AssertCompile(RT_ELEMENTS(pGMM->ahChunkMtx) < UINT8_MAX);
     1015        iChunkMtx %= RT_ELEMENTS(pGMM->aChunkMtx);
     1016
     1017        /* Try get an unused one... */
     1018        if (pGMM->aChunkMtx[iChunkMtx].cUsers)
     1019        {
     1020            iChunkMtx = pGMM->iNextChunkMtx++;
     1021            iChunkMtx %= RT_ELEMENTS(pGMM->aChunkMtx);
     1022            if (pGMM->aChunkMtx[iChunkMtx].cUsers)
     1023            {
     1024                iChunkMtx = pGMM->iNextChunkMtx++;
     1025                iChunkMtx %= RT_ELEMENTS(pGMM->aChunkMtx);
     1026                if (pGMM->aChunkMtx[iChunkMtx].cUsers)
     1027                {
     1028                    iChunkMtx = pGMM->iNextChunkMtx++;
     1029                    iChunkMtx %= RT_ELEMENTS(pGMM->aChunkMtx);
     1030                }
     1031            }
     1032        }
     1033
     1034        pChunk->iChunkMtx = iChunkMtx;
     1035    }
     1036    AssertCompile(RT_ELEMENTS(pGMM->aChunkMtx) < UINT8_MAX);
    10111037    pMtxState->iChunkMtx = (uint8_t)iChunkMtx;
     1038    ASMAtomicIncU32(&pGMM->aChunkMtx[iChunkMtx].cUsers);
    10121039
    10131040    /*
     
    10241051     * Take the chunk mutex.
    10251052     */
    1026     int rc = RTSemFastMutexRequest(pGMM->ahChunkMtx[iChunkMtx]);
     1053    int rc = RTSemFastMutexRequest(pGMM->aChunkMtx[iChunkMtx].hMtx);
    10271054    AssertRC(rc);
    10281055    return rc;
     
    10361063 * @param   pGMM        Pointer to the GMM instance.
    10371064 * @param   pChunk      Pointer to the chunk if it's still
    1038  *                      alive, NULL if it isn't.  This is
    1039  *                      inteded for later optimizations where we
    1040  *                      will deassociate the chunk mutex if
    1041  *                      considered safe.
     1065 *                      alive, NULL if it isn't.  This is used to deassociate
     1066 *                      the chunk from the mutex on the way out so a new one
     1067 *                      can be selected next time, thus avoiding contented
     1068 *                      mutexes.
    10421069 */
    10431070static int gmmR0ChunkMutexRelease(PGMMR0CHUNKMTXSTATE pMtxState, PGMMCHUNK pChunk)
    10441071{
    1045     int rc = RTSemFastMutexRelease(pMtxState->pGMM->ahChunkMtx[pMtxState->iChunkMtx]);
     1072    PGMM pGMM = pMtxState->pGMM;
     1073
     1074    /*
     1075     * Release the chunk mutex and reacquire the giant if requested.
     1076     */
     1077    int rc = RTSemFastMutexRelease(pGMM->aChunkMtx[pMtxState->iChunkMtx].hMtx);
    10461078    AssertRC(rc);
    10471079    if (pMtxState->fFlags == GMMR0CHUNK_MTX_RETAKE_GIANT)
    1048         rc = gmmR0MutexAcquire(pMtxState->pGMM);
     1080        rc = gmmR0MutexAcquire(pGMM);
     1081    else
     1082        Assert((pMtxState->fFlags != GMMR0CHUNK_MTX_DROP_GIANT) == (pGMM->hMtxOwner == RTThreadNativeSelf()));
     1083
     1084    /*
     1085     * Drop the chunk mutex user reference and deassociate it from the chunk
     1086     * when possible.
     1087     */
     1088    if (   ASMAtomicDecU32(&pGMM->aChunkMtx[pMtxState->iChunkMtx].cUsers) == 0
     1089        && pChunk
     1090        && RT_SUCCESS(rc) )
     1091    {
     1092        if (pMtxState->fFlags != GMMR0CHUNK_MTX_DROP_GIANT)
     1093            pChunk->iChunkMtx = UINT8_MAX;
     1094        else
     1095        {
     1096            rc = gmmR0MutexAcquire(pGMM);
     1097            if (RT_SUCCESS(rc))
     1098            {
     1099                if (pGMM->aChunkMtx[pMtxState->iChunkMtx].cUsers == 0)
     1100                    pChunk->iChunkMtx = UINT8_MAX;
     1101                rc = gmmR0MutexRelease(pGMM);
     1102            }
     1103        }
     1104    }
     1105
    10491106    pMtxState->pGMM = NULL;
    10501107    return rc;
     
    18781935        /*pChunk->iFreeHead = 0;*/
    18791936        pChunk->idNumaNode  = GMM_CHUNK_NUMA_ID_UNKNOWN;
     1937        pChunk->iChunkMtx   = UINT8_MAX;
    18801938        pChunk->fFlags      = fChunkFlags;
    18811939        for (unsigned iPage = 0; iPage < RT_ELEMENTS(pChunk->aPages) - 1; iPage++)
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette