third_party/virtualbox/src/VBox/VMM/VMMR3/MMHeap.cpp
/**
 * Allocate memory from the heap.
 *
 * @returns Pointer to allocated memory.
 * @param   pHeap       Heap handle.
 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
 *                      basis in addition to a global one. Thus we can easily
 *                      identify how memory is used by the VM. See MM_TAG_*.
 * @param   cbSize      Size of the block.
 * @param   fZero       Whether or not to zero the memory block.
 */
Allocate memory from the heap.
@returns Pointer to allocated memory.
@param   pHeap       Heap handle.
@param   enmTag      Statistics tag. Statistics are collected on a per tag
basis in addition to a global one. Thus we can easily
identify how memory is used by the VM.
Allocate memory from the heap . @returns Pointer to allocated memory . @param pHeap Heap handle . @param enmTag Statistics tag . Statistics are collected on a per tag basis in addition to a global one . Thus we can easily identify how memory is used by the VM .
void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero)
{
#ifdef MMR3HEAP_WITH_STATISTICS
    RTCritSectEnter(&pHeap->Lock);
    pHeap->Stat.cAllocations++;
    PMMHEAPSTAT pStat = (PMMHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);
    if (pStat)
    {
        pStat->cAllocations++;
        RTCritSectLeave(&pHeap->Lock);
    }
    else
    {
        pStat = (PMMHEAPSTAT)RTMemAllocZ(sizeof(MMHEAPSTAT));
        if (!pStat)
        {
            pHeap->Stat.cFailures++;
            AssertMsgFailed(("Failed to allocate heap stat record.\n"));
            RTCritSectLeave(&pHeap->Lock);
            return NULL;
        }
        pStat->Core.Key = (AVLULKEY)enmTag;
        pStat->pHeap    = pHeap;
        RTAvlULInsert(&pHeap->pStatTree, &pStat->Core);
        pStat->cAllocations++;
        RTCritSectLeave(&pHeap->Lock);
        PUVM pUVM = pHeap->pUVM;
        const char *pszTag = mmGetTagName(enmTag);
        STAMR3RegisterFU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of bytes currently allocated.",    "/MM/R3Heap/%s", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.",        "/MM/R3Heap/%s/cAllocations", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.",      "/MM/R3Heap/%s/cReallocations", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.",         "/MM/R3Heap/%s/cFrees", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of failures.",                     "/MM/R3Heap/%s/cFailures", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes allocated.",        "/MM/R3Heap/%s/cbAllocated", pszTag);
        STAMR3RegisterFU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes freed.",            "/MM/R3Heap/%s/cbFreed", pszTag);
    }
#else
    RT_NOREF_PV(enmTag);
#endif
    if (cbSize == 0)
    {
#ifdef MMR3HEAP_WITH_STATISTICS
        RTCritSectEnter(&pHeap->Lock);
        pStat->cFailures++;
        pHeap->Stat.cFailures++;
        RTCritSectLeave(&pHeap->Lock);
#endif
        AssertFailed();
        return NULL;
    }
    cbSize = RT_ALIGN_Z(cbSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
    PMMHEAPHDR const pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize));
    if (pHdr)
    {  }
    else
    {
        AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cbSize, enmTag, &enmTag));
#ifdef MMR3HEAP_WITH_STATISTICS
        RTCritSectEnter(&pHeap->Lock);
        pStat->cFailures++;
        pHeap->Stat.cFailures++;
        RTCritSectLeave(&pHeap->Lock);
#endif
        return NULL;
    }
    Assert(!((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)));
#ifdef MMR3HEAP_WITH_STATISTICS
    pHdr->pStat  = pStat;
#else
    pHdr->pStat  = &pHeap->Stat;
#endif
    pHdr->cbSize = cbSize;
    RTCritSectEnter(&pHeap->Lock);
    mmR3HeapLink(pHeap, pHdr);
#ifdef MMR3HEAP_WITH_STATISTICS
    pStat->cbAllocated          += cbSize;
    pStat->cbCurAllocated       += cbSize;
    pHeap->Stat.cbAllocated     += cbSize;
    pHeap->Stat.cbCurAllocated  += cbSize;
#endif
    RTCritSectLeave(&pHeap->Lock);
    return pHdr + 1;
}
void * mmR3HeapAlloc ( PMMHEAP pHeap , MMTAG enmTag , size_t cbSize , bool fZero ) { #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter ( & pHeap -> Lock ) ; pHeap -> Stat . cAllocations ++ ; PMMHEAPSTAT pStat = ( PMMHEAPSTAT ) RTAvlULGet ( & pHeap -> pStatTree , ( AVLULKEY ) enmTag ) ; if ( pStat ) { pStat -> cAllocations ++ ; RTCritSectLeave ( & pHeap -> Lock ) ; } else { pStat = ( PMMHEAPSTAT ) RTMemAllocZ ( sizeof ( MMHEAPSTAT ) ) ; if ( ! pStat ) { pHeap -> Stat . cFailures ++ ; AssertMsgFailed ( ( " \n " ) ) ; RTCritSectLeave ( & pHeap -> Lock ) ; return NULL ; } pStat -> Core . Key = ( AVLULKEY ) enmTag ; pStat -> pHeap = pHeap ; RTAvlULInsert ( & pHeap -> pStatTree , & pStat -> Core ) ; pStat -> cAllocations ++ ; RTCritSectLeave ( & pHeap -> Lock ) ; PUVM pUVM = pHeap -> pUVM ; const char * pszTag = mmGetTagName ( enmTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cbCurAllocated , STAMTYPE_U32 , STAMVISIBILITY_ALWAYS , STAMUNIT_BYTES , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cAllocations , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_CALLS , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cReallocations , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_CALLS , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cFrees , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_CALLS , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cFailures , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_COUNT , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cbAllocated , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_BYTES , " " , " " , pszTag ) ; STAMR3RegisterFU ( pUVM , & pStat -> cbFreed , STAMTYPE_U64 , STAMVISIBILITY_ALWAYS , STAMUNIT_BYTES , " " , " " , pszTag ) ; } #else RT_NOREF_PV ( enmTag ) ; #endif if ( cbSize == 0 ) { #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter ( & pHeap -> Lock ) ; pStat -> cFailures ++ ; pHeap -> Stat . cFailures ++ ; RTCritSectLeave ( & pHeap -> Lock ) ; #endif AssertFailed ( ) ; return NULL ; } cbSize = RT_ALIGN_Z ( cbSize , MMR3HEAP_SIZE_ALIGNMENT ) + sizeof ( MMHEAPHDR ) ; PMMHEAPHDR const pHdr = ( PMMHEAPHDR ) ( fZero ? RTMemAllocZ ( cbSize ) : RTMemAlloc ( cbSize ) ) ; if ( pHdr ) { } else { AssertMsgFailed ( ( " \n " , cbSize , enmTag , & enmTag ) ) ; #ifdef MMR3HEAP_WITH_STATISTICS RTCritSectEnter ( & pHeap -> Lock ) ; pStat -> cFailures ++ ; pHeap -> Stat . cFailures ++ ; RTCritSectLeave ( & pHeap -> Lock ) ; #endif return NULL ; } Assert ( ! ( ( uintptr_t ) pHdr & ( RTMEM_ALIGNMENT - 1 ) ) ) ; #ifdef MMR3HEAP_WITH_STATISTICS pHdr -> pStat = pStat ; #else pHdr -> pStat = & pHeap -> Stat ; #endif pHdr -> cbSize = cbSize ; RTCritSectEnter ( & pHeap -> Lock ) ; mmR3HeapLink ( pHeap , pHdr ) ; #ifdef MMR3HEAP_WITH_STATISTICS pStat -> cbAllocated += cbSize ; pStat -> cbCurAllocated += cbSize ; pHeap -> Stat . cbAllocated += cbSize ; pHeap -> Stat . cbCurAllocated += cbSize ; #endif RTCritSectLeave ( & pHeap -> Lock ) ; return pHdr + 1 ; }
Allocate memory from the heap.
Allocate memory from the heap .
/*
     * Find/alloc statistics nodes.
     */ /* register the statistics */ /*
     * Validate input.
     */ /*
     * Allocate heap block.
     */ /* likely */ /*
     * Init and link in the header.
     */ /*
     * Update statistics
     */