VirtualBox

Changeset 97921 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Dec 30, 2022 9:15:10 PM (2 years ago)
Author:
vboxsync
Message:

Add/VBoxGuestR0LibPhysHeap.cpp: Count both kind of blocks both on heap and chunk level. This is in preparation for a workaround for VbglR0PhysHeapFree not merging with the block before the one that getting freed. Completed the vbglR0PhysHeapCheckLocked code.

Location:
trunk/src/VBox/Additions/common/VBoxGuest/lib
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibInternal.h

    r97913 r97921  
    119119/**
    120120 * Global VBGL ring-0 data.
    121  * Lives in VbglR0Init.cpp.
     121 * Lives in VBoxGuestR0LibInit.cpp.
    122122 */
    123123typedef struct VBGLDATA
     
    132132     * @{
    133133     */
     134    RTSEMFASTMUTEX     mutexHeap;
    134135    VBGLPHYSHEAPBLOCK *pFreeBlocksHead;
    135136    VBGLPHYSHEAPBLOCK *pAllocBlocksHead;
     137    /** Indexed by VBGLPHYSHEAPBLOCK::fAllocated, so zero is the free ones and
     138     *  one the allocated ones. */
     139    int32_t            acBlocks[2];
    136140    VBGLPHYSHEAPCHUNK *pChunkHead;
    137 
    138     RTSEMFASTMUTEX     mutexHeap;
    139141    /** @} */
    140142
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibPhysHeap.cpp

    r97919 r97921  
    145145    uint32_t physAddr;
    146146
    147     /** Number of allocated blocks in the chunk */
    148     int32_t cAllocatedBlocks;
     147    uint32_t uPadding1;
     148
     149    /** Indexed by VBGLPHYSHEAPBLOCK::fAllocated, so zero is the free ones and
     150     *  one the allocated ones. */
     151    int32_t acBlocks[2];
    149152
    150153    /** Pointer to the next chunk. */
     
    152155    /** Pointer to the previous chunk. */
    153156    VBGLPHYSHEAPCHUNK  *pPrev;
     157#if ARCH_BITS == 64
     158    /** Pad the size up to 64 bytes. */
     159    uintptr_t           auPadding2[3];
     160#endif
    154161};
     162#if ARCH_BITS == 64
     163AssertCompileSize(VBGLPHYSHEAPCHUNK, 64);
     164#endif
    155165
    156166
     
    257267
    258268
     269/**
     270 * Links @a pBlock onto the appropriate chain accoring to @a pInsertAfter or @a
     271 * pBlock->fAllocated.
     272 *
     273 * This also update the per-chunk block counts.
     274 */
    259275static void vbglPhysHeapInsertBlock(VBGLPHYSHEAPBLOCK *pInsertAfter, VBGLPHYSHEAPBLOCK *pBlock)
    260276{
     277    bool const fAllocated = pBlock->fAllocated;
     278
    261279    VBGL_PH_ASSERT_MSG(pBlock->pNext == NULL, ("pBlock->pNext = %p\n", pBlock->pNext));
    262280    VBGL_PH_ASSERT_MSG(pBlock->pPrev == NULL, ("pBlock->pPrev = %p\n", pBlock->pPrev));
     
    277295        pBlock->pPrev = NULL;
    278296
    279         if (pBlock->fAllocated)
     297        if (fAllocated)
    280298        {
    281299            pBlock->pNext = g_vbgldata.pAllocBlocksHead;
     
    296314        }
    297315    }
     316
     317    /* Update the block counts: */
     318    g_vbgldata.acBlocks[fAllocated]      += 1;
     319    pBlock->pChunk->acBlocks[fAllocated] += 1;
     320    AssertMsg(   (uint32_t)pBlock->pChunk->acBlocks[fAllocated]
     321              <= pBlock->pChunk->cbSize / (sizeof(*pBlock) + sizeof(void *)),
     322              ("pChunk=%p: cbSize=%#x acBlocks[%u]=%d\n",
     323               pBlock->pChunk, pBlock->pChunk->cbSize, pBlock->pChunk->acBlocks[fAllocated]));
    298324}
    299325
    300326
    301327/**
    302  * Unlinks @a pBlock from the chain its on.
     328 * Unlinks @a pBlock from the chain it's on.
     329 *
     330 * This also update the per-chunk block counts.
    303331 */
    304332static void vbglPhysHeapExcludeBlock(VBGLPHYSHEAPBLOCK *pBlock)
    305333{
     334    bool const fAllocated = pBlock->fAllocated;
     335
    306336    if (pBlock->pNext)
    307337        pBlock->pNext->pPrev = pBlock->pPrev;
     
    310340    if (pBlock->pPrev)
    311341        pBlock->pPrev->pNext = pBlock->pNext;
    312     else if (pBlock->fAllocated)
     342    else if (fAllocated)
    313343    {
    314344        Assert(g_vbgldata.pAllocBlocksHead == pBlock);
     
    323353    pBlock->pNext = NULL;
    324354    pBlock->pPrev = NULL;
    325 }
     355
     356    /* Update the per-chunk counts: */
     357    g_vbgldata.acBlocks[fAllocated]      -= 1;
     358    pBlock->pChunk->acBlocks[fAllocated] -= 1;
     359    AssertMsg(pBlock->pChunk->acBlocks[fAllocated] >= 0,
     360              ("pChunk=%p: cbSize=%#x acBlocks[%u]=%d\n",
     361               pBlock->pChunk, pBlock->pChunk->cbSize, pBlock->pChunk->acBlocks[fAllocated]));
     362    Assert(g_vbgldata.acBlocks[fAllocated] >= 0);
     363}
     364
    326365
    327366static VBGLPHYSHEAPBLOCK *vbglPhysHeapChunkAlloc(uint32_t cbMinBlock)
     
    355394        pChunk->cbSize           = cbChunk;
    356395        pChunk->physAddr         = (uint32_t)PhysAddr;
    357         pChunk->cAllocatedBlocks = 0;
     396        pChunk->acBlocks[0]      = 0;
     397        pChunk->acBlocks[1]      = 0;
    358398        pChunk->pNext            = NULL;
    359399        pChunk->pPrev            = NULL;
     400        pChunk->uPadding1        = UINT32_C(0xADDCAAA1);
     401#if ARCH_BITS == 64
     402        pChunk->auPadding2[0]    = UINT64_C(0xADDCAAA3ADDCAAA2);
     403        pChunk->auPadding2[1]    = UINT64_C(0xADDCAAA5ADDCAAA4);
     404        pChunk->auPadding2[2]    = UINT64_C(0xADDCAAA7ADDCAAA6);
     405#endif
    360406
    361407        /* Initialize the free block, which now occupies entire chunk. */
     
    532578        /* Insert to allocated list */
    533579        vbglPhysHeapInsertBlock(NULL, pBlock);
    534 
    535         /* Adjust the chunk allocated blocks counter */
    536         pBlock->pChunk->cAllocatedBlocks++;
    537580    }
    538581
     
    560603    return physAddr;
    561604}
     605
    562606
    563607DECLR0VBGL(void) VbglR0PhysHeapFree(void *pv)
     
    571615        return;
    572616
    573     dumpheap ("pre free");
     617    dumpheap("pre free");
    574618
    575619    pBlock = vbglPhysHeapData2Block(pv);
     
    598642    dumpheap("post insert");
    599643
    600     /* Adjust the chunk allocated blocks counter */
    601644    pChunk = pBlock->pChunk;
    602     pChunk->cAllocatedBlocks--;
    603 
    604     VBGL_PH_ASSERT(pChunk->cAllocatedBlocks >= 0);
    605645
    606646    /* Check if we can merge 2 free blocks. To simplify heap maintenance,
     
    631671
    632672    /* now check if there are 2 or more free (unused) chunks */
    633     if (pChunk->cAllocatedBlocks == 0)
     673    if (pChunk->acBlocks[1 /*allocated*/] == 0)
    634674    {
    635675        VBGLPHYSHEAPCHUNK *pCurChunk;
     
    640680        {
    641681            Assert(pCurChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE);
    642             if (pCurChunk->cAllocatedBlocks == 0)
     682            if (pCurChunk->acBlocks[1 /*allocated*/] == 0)
    643683                cUnusedChunks++;
    644684        }
     
    687727}
    688728
     729
     730/**
     731 * Checks the heap, caller responsible for locking.
     732 *
     733 * @returns VINF_SUCCESS if okay, error status if not.
     734 * @param   pErrInfo    Where to return more error details, optional.
     735 */
    689736static int vbglR0PhysHeapCheckLocked(PRTERRINFO pErrInfo)
    690737{
     
    692739     * Scan the blocks in each chunk.
    693740     */
    694     unsigned cTotalFreeBlocks = 0;
    695     unsigned cTotalUsedBlocks = 0;
    696     for (VBGLPHYSHEAPCHUNK *pCurChunk = g_vbgldata.pChunkHead; pCurChunk; pCurChunk = pCurChunk->pNext)
     741    unsigned acTotalBlocks[2] = { 0, 0 };
     742    for (VBGLPHYSHEAPCHUNK *pCurChunk = g_vbgldata.pChunkHead, *pPrevChunk = NULL; pCurChunk; pCurChunk = pCurChunk->pNext)
    697743    {
    698744        AssertReturn(pCurChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE,
    699                      RTErrInfoSetF(pErrInfo, VERR_INVALID_MAGIC, "pCurChunk=%p: magic=%#x\n", pCurChunk, pCurChunk->u32Signature));
     745                     RTErrInfoSetF(pErrInfo, VERR_INVALID_MAGIC, "pCurChunk=%p: magic=%#x", pCurChunk, pCurChunk->u32Signature));
     746        AssertReturn(pCurChunk->pPrev == pPrevChunk,
     747                     RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_2,
     748                                   "pCurChunk=%p: pPrev=%p, expected %p", pCurChunk, pCurChunk->pPrev, pPrevChunk));
    700749
    701750        uintptr_t const          uEnd        = (uintptr_t)pCurChunk + pCurChunk->cbSize;
    702751        const VBGLPHYSHEAPBLOCK *pCurBlock   = (const VBGLPHYSHEAPBLOCK *)(pCurChunk + 1);
    703         unsigned                 cUsedBlocks = 0;
     752        unsigned                 acBlocks[2] = { 0, 0 };
    704753        while ((uintptr_t)pCurBlock < uEnd)
    705754        {
    706755            AssertReturn(pCurBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
    707756                         RTErrInfoSetF(pErrInfo, VERR_INVALID_MAGIC,
    708                                        "pCurBlock=%p: magic=%#x\n", pCurBlock, pCurBlock->u32Signature));
     757                                       "pCurBlock=%p: magic=%#x", pCurBlock, pCurBlock->u32Signature));
    709758            AssertReturn(pCurBlock->pChunk == pCurChunk,
    710759                         RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_2,
    711                                        "pCurBlock=%p: pChunk=%p, expected %p\n", pCurBlock, pCurBlock->pChunk, pCurChunk));
    712             AssertReturn(   pCurBlock->cbDataSize >= 8
     760                                       "pCurBlock=%p: pChunk=%p, expected %p", pCurBlock, pCurBlock->pChunk, pCurChunk));
     761            AssertReturn(   pCurBlock->cbDataSize >= sizeof(void *)
    713762                         && pCurBlock->cbDataSize < _128M
    714763                         && RT_ALIGN_32(pCurBlock->cbDataSize, sizeof(void *)) == pCurBlock->cbDataSize,
    715764                         RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_3,
    716                                        "pCurBlock=%p: cbDataSize=%#x\n", pCurBlock, pCurBlock->cbDataSize));
    717             if (pCurBlock->fAllocated)
    718                 cUsedBlocks += 1;
    719             else
    720                 cTotalFreeBlocks += 1;
     765                                       "pCurBlock=%p: cbDataSize=%#x", pCurBlock, pCurBlock->cbDataSize));
     766            acBlocks[pCurBlock->fAllocated] += 1;
    721767
    722768            /* advance */
     
    725771        AssertReturn((uintptr_t)pCurBlock == uEnd,
    726772                     RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_4,
    727                                    "pCurBlock=%p uEnd=%p\n", pCurBlock, uEnd));
    728         AssertReturn(cUsedBlocks == (uint32_t)pCurChunk->cAllocatedBlocks,
     773                                   "pCurBlock=%p uEnd=%p", pCurBlock, uEnd));
     774
     775        acTotalBlocks[1] += acBlocks[1];
     776        AssertReturn(acBlocks[1] == (uint32_t)pCurChunk->acBlocks[1],
    729777                     RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_4,
    730                                    "pCurChunk=%p: cAllocatedBlocks=%u, expected %u\n",
    731                                    pCurChunk, pCurChunk->cAllocatedBlocks, cUsedBlocks));
    732         cTotalUsedBlocks += cUsedBlocks;
    733     }
     778                                   "pCurChunk=%p: cAllocatedBlocks=%u, expected %u",
     779                                   pCurChunk, pCurChunk->acBlocks[1], acBlocks[1]));
     780
     781        acTotalBlocks[0] += acBlocks[0];
     782        AssertReturn(acBlocks[0] == (uint32_t)pCurChunk->acBlocks[0],
     783                     RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_5,
     784                                   "pCurChunk=%p: cFreeBlocks=%u, expected %u",
     785                                   pCurChunk, pCurChunk->acBlocks[0], acBlocks[0]));
     786
     787        pPrevChunk = pCurChunk;
     788    }
     789
     790    AssertReturn(acTotalBlocks[0] == (uint32_t)g_vbgldata.acBlocks[0],
     791                 RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR,
     792                               "g_vbgldata.acBlocks[0]=%u, expected %u", g_vbgldata.acBlocks[0], acTotalBlocks[0]));
     793    AssertReturn(acTotalBlocks[1] == (uint32_t)g_vbgldata.acBlocks[1],
     794                 RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR,
     795                               "g_vbgldata.acBlocks[1]=%u, expected %u", g_vbgldata.acBlocks[1], acTotalBlocks[1]));
     796
     797    /*
     798     * Count each list and check that they contain the same number of nodes.
     799     */
     800    VBGLPHYSHEAPBLOCK *apHeads[2] = { g_vbgldata.pFreeBlocksHead, g_vbgldata.pAllocBlocksHead };
     801    for (unsigned iType = 0; iType < RT_ELEMENTS(apHeads); iType++)
     802    {
     803        unsigned           cBlocks    = 0;
     804        VBGLPHYSHEAPBLOCK *pPrevBlock = NULL;
     805        for (VBGLPHYSHEAPBLOCK *pCurBlock = apHeads[iType]; pCurBlock; pCurBlock = pCurBlock->pNext)
     806        {
     807            AssertReturn(pCurBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
     808                         RTErrInfoSetF(pErrInfo, VERR_INVALID_MAGIC,
     809                                       "pCurBlock=%p/%u: magic=%#x", pCurBlock, iType, pCurBlock->u32Signature));
     810            AssertReturn(pCurBlock->pPrev == pPrevBlock,
     811                         RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_2,
     812                                       "pCurBlock=%p/%u: pPrev=%p, expected %p", pCurBlock, iType, pCurBlock->pPrev, pPrevBlock));
     813            AssertReturn(pCurBlock->pChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE,
     814                         RTErrInfoSetF(pErrInfo, VERR_INVALID_MAGIC, "pCurBlock=%p/%u: chunk (%p) magic=%#x",
     815                                       pCurBlock, iType, pCurBlock->pChunk, pCurBlock->pChunk->u32Signature));
     816            cBlocks++;
     817            pPrevBlock = pCurBlock;
     818        }
     819
     820        AssertReturn(cBlocks == acTotalBlocks[iType],
     821                     RTErrInfoSetF(pErrInfo, VERR_INTERNAL_ERROR_3,
     822                                   "iType=%u: Found %u in list, expected %u", iType, cBlocks, acTotalBlocks[iType]));
     823    }
     824
    734825    return VINF_SUCCESS;
    735826}
     827
    736828
    737829/**
     
    739831 *
    740832 * @returns Problem description on failure, NULL on success.
     833 * @param   pErrInfo    Where to return more error details, optional.
    741834 */
    742835DECLVBGL(int) VbglR0PhysHeapCheck(PRTERRINFO pErrInfo)
     
    751844}
    752845
    753 
    754846#endif /* IN_TESTCASE */
    755 
    756847
    757848DECLR0VBGL(int) VbglR0PhysHeapInit(void)
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/testcase/tstVbglR0PhysHeap-1.cpp

    r97913 r97921  
    345345                s_aHistory[i].pv = NULL;
    346346            }
     347            RTTestIPrintf(RTTESTLVL_ALWAYS, "after free-all: cFreeBlocks=%u in %u chunk(s)\n", g_vbgldata.acBlocks[0], g_cChunks);
    347348            RTTESTI_CHECK_MSG(g_cChunks == 1, ("g_cChunks=%d\n", g_cChunks));
     349            RTTESTI_CHECK_MSG(g_vbgldata.acBlocks[1] == 0, ("g_vbgldata.acBlocks[1]=%d\n", g_vbgldata.acBlocks[0]));
    348350#if 0
    349351            for (VBGLPHYSHEAPCHUNK *pCurChunk = g_vbgldata.pChunkHead; pCurChunk; pCurChunk = pCurChunk->pNext)
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