VirtualBox

Ignore:
Timestamp:
Nov 28, 2009 2:29:46 AM (15 years ago)
Author:
vboxsync
Message:

rtHeapOffsetAllocBlock: Rewrote the alignment handling so it doesn't blow up nor leaks memory.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/alloc/heapoffset.cpp

    r25060 r25065  
    196196 */
    197197#ifdef RTHEAPOFFSET_STRICT
    198 # define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off) )
     198# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type)   ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, true /*fNull*/) )
    199199#else
    200 # define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)((off) ? (uint8_t *)(pHeapInt) + (off) : NULL) )
     200# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type)   ( (type)((off) ? (uint8_t *)(pHeapInt) + (off) : NULL) )
     201#endif
     202
     203/**
     204 * Converts an offset to a pointer.
     205 *
     206 * All offsets are relative to the heap to make life simple.
     207 *
     208 * @returns Pointer of given type.
     209 * @param   pHeapInt        Pointer to the heap anchor block.
     210 * @param   off             The offset to convert.
     211 * @param   type            The desired type.
     212 */
     213#ifdef RTHEAPOFFSET_STRICT
     214# define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, false /*fNull*/) )
     215#else
     216# define RTHEAPOFF_TO_PTR(pHeapInt, off, type)   ( (type)((uint8_t *)(pHeapInt) + (off)) )
    201217#endif
    202218
     
    323339#ifdef RTHEAPOFFSET_STRICT
    324340
    325 /** Checked version of RTHEAPOFF_TO_PTR. */
    326 DECLINLINE(void *) rtHeapOffCheckedOffToPtr(PRTHEAPOFFSETINTERNAL pHeapInt, uint32_t off)
    327 {
     341/** Checked version of RTHEAPOFF_TO_PTR and RTHEAPOFF_TO_PTR_N. */
     342DECLINLINE(void *) rtHeapOffCheckedOffToPtr(PRTHEAPOFFSETINTERNAL pHeapInt, uint32_t off, bool fNull)
     343{
     344    Assert(off || fNull);
    328345    if (!off)
    329346        return NULL;
     
    505522     * Search for a fitting block from the lower end of the heap.
    506523     */
    507     for (pFree = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
     524    for (pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
    508525         pFree;
    509          pFree = RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE))
     526         pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE))
    510527    {
    511528        uintptr_t offAlign;
     
    520537        if (offAlign)
    521538        {
     539#define DONT_DONATE_ALIGNMENT
     540#ifdef DONT_DONATE_ALIGNMENT
     541            PRTHEAPOFFSETFREE pPrev;
     542
     543            offAlign = (uintptr_t)(&pFree[1].Core + 1) & (uAlignment - 1);
     544            offAlign = uAlignment - offAlign;
     545            if (pFree->cb < cb + offAlign + sizeof(RTHEAPOFFSETFREE))
     546                continue;
     547
     548            /*
     549             * Split up the free block into two, so that the 2nd is aligned as
     550             * per specification.
     551             */
     552            pPrev = pFree;
     553            pFree = (PRTHEAPOFFSETFREE)((uintptr_t)(pFree + 1) + offAlign);
     554            pFree->Core.offPrev = pPrev->Core.offSelf;
     555            pFree->Core.offNext = pPrev->Core.offNext;
     556            pFree->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
     557            pFree->Core.fFlags  = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
     558            pFree->offPrev      = pPrev->Core.offSelf;
     559            pFree->offNext      = pPrev->offNext;
     560            pFree->cb           = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap)
     561                                - pFree->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
     562
     563            pPrev->Core.offNext = pFree->Core.offSelf;
     564            pPrev->offNext      = pFree->Core.offSelf;
     565            pPrev->cb           = pFree->Core.offSelf - pPrev->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
     566
     567            if (pFree->Core.offNext)
     568                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pFree->Core.offSelf;
     569            if (pFree->offNext)
     570                RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->Core.offSelf;
     571            else
     572                pHeapInt->offFreeTail = pFree->Core.offSelf;
     573
     574            pHeapInt->cbFree -= sizeof(RTHEAPOFFSETBLOCK);
     575            ASSERT_BLOCK_FREE(pHeapInt, pPrev);
     576            ASSERT_BLOCK_FREE(pHeapInt, pFree);
     577
     578#else  /* !DONT_DONATE_ALIGNMENT */
    522579            RTHEAPOFFSETFREE Free;
    523580            PRTHEAPOFFSETBLOCK pPrev;
     
    542599             * for that.)
    543600             */
    544             pPrev = RTHEAPOFF_TO_PTR(pHeapInt, Free.Core.offPrev, PRTHEAPOFFSETBLOCK);
     601            pPrev = RTHEAPOFF_TO_PTR_N(pHeapInt, Free.Core.offPrev, PRTHEAPOFFSETBLOCK);
    545602            if (pPrev)
    546603            {
     
    582639            ASSERT_BLOCK_FREE(pHeapInt, pFree);
    583640            ASSERT_BLOCK_USED(pHeapInt, pPrev);
     641#endif /* !DONT_DONATE_ALIGNMENT */
    584642        }
    585643
     
    590648        {
    591649            /*
    592              * Move the FREE block up to make room for the new USED block.
     650             * Create a new FREE block at then end of this one.
    593651             */
    594652            PRTHEAPOFFSETFREE   pNew = (PRTHEAPOFFSETFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPOFFSETBLOCK));
     
    616674
    617675            /*
    618              * Update the old FREE node making it a USED node.
     676             * Adjust and convert the old FREE node into a USED node.
    619677             */
    620678            pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE;
     
    720778    if (pHeapInt->offFreeTail)
    721779    {
    722         pRight = RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE);
     780        pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE);
    723781        while (pRight && !RTHEAPOFFSETBLOCK_IS_FREE(&pRight->Core))
    724782        {
    725783            ASSERT_BLOCK(pHeapInt, &pRight->Core);
    726             pRight = RTHEAPOFF_TO_PTR(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETFREE);
     784            pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETFREE);
    727785        }
    728786        if (!pRight)
    729             pLeft = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeTail, PRTHEAPOFFSETFREE);
     787            pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeTail, PRTHEAPOFFSETFREE);
    730788        else
    731789        {
    732790            ASSERT_BLOCK_FREE(pHeapInt, pRight);
    733             pLeft = RTHEAPOFF_TO_PTR(pHeapInt, pRight->offPrev, PRTHEAPOFFSETFREE);
     791            pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->offPrev, PRTHEAPOFFSETFREE);
    734792        }
    735793        if (pLeft)
     
    739797    ASSERT_L(RTHEAPOFF_TO_OFF(pHeapInt, pLeft), RTHEAPOFF_TO_OFF(pHeapInt, pFree));
    740798    Assert(!pRight || (uintptr_t)pRight > (uintptr_t)pFree);
    741     Assert(!pLeft || RTHEAPOFF_TO_PTR(pHeapInt, pLeft->offNext, PRTHEAPOFFSETFREE) == pRight);
     799    Assert(!pLeft || RTHEAPOFF_TO_PTR_N(pHeapInt, pLeft->offNext, PRTHEAPOFFSETFREE) == pRight);
    742800
    743801    /*
     
    746804    if (!pLeft)
    747805    {
    748         Assert(pRight == RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE));
     806        Assert(pRight == RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE));
    749807        pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE;
    750808        pFree->offPrev = 0;
     
    831889    for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
    832890         pBlock;
    833          pBlock = RTHEAPOFF_TO_PTR(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
     891         pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
    834892    {
    835893        if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core))
     
    923981    for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
    924982         pBlock;
    925          pBlock = RTHEAPOFF_TO_PTR(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
     983         pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
    926984    {
    927985        size_t cb = (pBlock->offNext ? pBlock->Core.offNext : pHeapInt->cbHeap)
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