VirtualBox

vbox的更動 18792 路徑 trunk/src/VBox/VMM/MMUkHeap.cpp


忽略:
時間撮記:
2009-4-6 下午06:40:52 (16 年 以前)
作者:
vboxsync
訊息:

MM,PGM: New User-kernel heap (aka MMUkHeap), use it for the PGMCHUNKR3MAP instead of the hyper heap.

檔案:
複製 1 筆資料

圖例:

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

    • 屬性 svn:keywordsId 變更至 Author Date Id Revision
    r18763 r18792  
    11/* $Id$ */
    22/** @file
    3  * MM - Memory Manager - Heap.
     3 * MM - Memory Manager - Ring-3 Heap with kernel accessible mapping.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2727#include <VBox/mm.h>
    2828#include <VBox/stam.h>
    29 #include <VBox/pgm.h>
    3029#include "MMInternal.h"
    3130#include <VBox/vm.h>
     
    3534#include <VBox/log.h>
    3635
    37 #include <iprt/alloc.h>
    3836#include <iprt/assert.h>
    3937#include <iprt/string.h>
     38#include <iprt/heap.h>
    4039
    4140
     
    4342*   Internal Functions                                                         *
    4443*******************************************************************************/
    45 static void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero);
    46 
    47 
    48 
    49 /**
    50  * Allocate and initialize a heap structure and it's associated substructures.
     44static void *mmR3UkHeapAlloc(PMMUKHEAP pHeap, MMTAG enmTag, size_t cb, bool fZero, PRTR0PTR pR0Ptr);
     45
     46
     47
     48/**
     49 * Create a User-kernel heap.
     50 *
     51 * This does not require SUPLib to be initialized as we'll lazily allocate the
     52 * kernel accessible memory on the first alloc call.
    5153 *
    5254 * @returns VBox status.
     
    5456 * @param   ppHeap  Where to store the heap pointer.
    5557 */
    56 int mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap)
    57 {
    58     PMMHEAP pHeap = (PMMHEAP)RTMemAllocZ(sizeof(MMHEAP) + sizeof(MMHEAPSTAT));
     58int mmR3UkHeapCreateU(PUVM pUVM, PMMUKHEAP *ppHeap)
     59{
     60    PMMUKHEAP pHeap = (PMMUKHEAP)MMR3HeapAllocZU(pUVM, MM_TAG_MM, sizeof(MMUKHEAP));
    5961    if (pHeap)
    6062    {
     
    6668             */
    6769            pHeap->pUVM = pUVM;
    68             pHeap->Stat.pHeap = pHeap;
    69 #ifdef MMR3HEAP_WITH_STATISTICS
    70             PMMHEAPSTAT pStat = &pHeap->Stat;
    71             STAMR3RegisterU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cAllocations",     STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
    72             STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cReallocations",   STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
    73             STAMR3RegisterU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFrees",           STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
    74             STAMR3RegisterU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFailures",        STAMUNIT_COUNT, "Number of failures.");
     70#ifdef MMUKHEAP_WITH_STATISTICS
     71            PMMUKHEAPSTAT pStat = &pHeap->Stat;
     72            STAMR3RegisterU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cAllocations",     STAMUNIT_CALLS, "Number or MMR3UkHeapAlloc() calls.");
     73            STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cReallocations",   STAMUNIT_CALLS, "Number of MMR3UkHeapRealloc() calls.");
     74            STAMR3RegisterU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cFrees",           STAMUNIT_CALLS, "Number of MMR3UkHeapFree() calls.");
     75            STAMR3RegisterU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cFailures",        STAMUNIT_COUNT, "Number of failures.");
    7576            STAMR3RegisterU(pUVM, &pStat->cbCurAllocated, sizeof(pStat->cbCurAllocated) == sizeof(uint32_t) ? STAMTYPE_U32 : STAMTYPE_U64,
    76                                                                         STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbCurAllocated",   STAMUNIT_BYTES, "Number of bytes currently allocated.");
    77             STAMR3RegisterU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbAllocated",      STAMUNIT_BYTES, "Total number of bytes allocated.");
    78             STAMR3RegisterU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbFreed",          STAMUNIT_BYTES, "Total number of bytes freed.");
     77                                                                        STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cbCurAllocated",   STAMUNIT_BYTES, "Number of bytes currently allocated.");
     78            STAMR3RegisterU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cbAllocated",      STAMUNIT_BYTES, "Total number of bytes allocated.");
     79            STAMR3RegisterU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/UkHeap/cbFreed",          STAMUNIT_BYTES, "Total number of bytes freed.");
    7980#endif
    8081            *ppHeap = pHeap;
     
    8283        }
    8384        AssertRC(rc);
    84         RTMemFree(pHeap);
     85        MMR3HeapFree(pHeap);
    8586    }
    8687    AssertMsgFailed(("failed to allocate heap structure\n"));
     
    9091
    9192/**
    92  * Destroy a heap.
     93 * Destroy a User-kernel heap.
    9394 *
    9495 * @param   pHeap   Heap handle.
    9596 */
    96 void mmR3HeapDestroy(PMMHEAP pHeap)
     97void mmR3UkHeapDestroy(PMMUKHEAP pHeap)
    9798{
    9899    /*
     
    103104
    104105    /*
    105      * Walk the node list and free all the memory.
    106      */
    107     PMMHEAPHDR  pHdr = pHeap->pHead;
    108     while (pHdr)
    109     {
    110         void *pv = pHdr;
    111         pHdr = pHdr->pNext;
    112         RTMemFree(pv);
    113     }
    114 
    115     /*
    116      * Free the stat nodes.
    117      */
    118     /** @todo free all nodes in a AVL tree. */
    119     RTMemFree(pHeap);
    120 }
    121 
    122 
    123 /**
    124  * Allocate memory associating it with the VM for collective cleanup.
    125  *
    126  * The memory will be allocated from the default heap but a header
    127  * is added in which we keep track of which VM it belongs to and chain
    128  * all the allocations together so they can be freed in one go.
    129  *
    130  * This interface is typically used for memory block which will not be
    131  * freed during the life of the VM.
    132  *
    133  * @returns Pointer to allocated memory.
    134  * @param   pUVM        Pointer to the user mode VM structure.
    135  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    136  *                      basis in addition to a global one. Thus we can easily
    137  *                      identify how memory is used by the VM.
    138  * @param   cbSize      Size of the block.
    139  */
    140 VMMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
    141 {
    142     Assert(pUVM->mm.s.pHeap);
    143     return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
     106     * Walk the sub-heaps and free them.
     107     */
     108    while (pHeap->pSubHeapHead)
     109    {
     110        PMMUKHEAPSUB pSubHeap = pHeap->pSubHeapHead;
     111        pHeap->pSubHeapHead = pSubHeap->pNext;
     112        SUPR3PageFreeEx(pSubHeap->pv, pSubHeap->cb >> PAGE_SHIFT);
     113        //MMR3HeapFree(pSubHeap); - rely on the automatic cleanup.
     114    }
     115    //MMR3HeapFree(pHeap->stats);
     116    //MMR3HeapFree(pHeap);
    144117}
    145118
     
    161134 *                      identify how memory is used by the VM.
    162135 * @param   cbSize      Size of the block.
    163  */
    164 VMMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize)
    165 {
    166     return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
    167 }
    168 
    169 
    170 /**
    171  * Same as MMR3HeapAllocU().
    172  *
    173  * @returns Pointer to allocated memory.
    174  * @param   pUVM        Pointer to the user mode VM structure.
    175  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    176  *                      basis in addition to a global one. Thus we can easily
    177  *                      identify how memory is used by the VM.
    178  * @param   cbSize      Size of the block.
    179  * @param   ppv         Where to store the pointer to the allocated memory on success.
    180  */
    181 VMMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
    182 {
    183     Assert(pUVM->mm.s.pHeap);
    184     void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
    185     if (pv)
    186     {
    187         *ppv = pv;
    188         return VINF_SUCCESS;
    189     }
    190     return VERR_NO_MEMORY;
    191 }
    192 
    193 
    194 /**
    195  * Same as MMR3HeapAlloc().
     136 * @param   pR0Ptr      Where to return the ring-0 address of the memory.
     137 */
     138VMMR3DECL(void *) MMR3UkHeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr)
     139{
     140    return mmR3UkHeapAlloc(pVM->pUVM->mm.s.pUkHeap, enmTag, cbSize, false, pR0Ptr);
     141}
     142
     143
     144/**
     145 * Same as MMR3UkHeapAlloc().
    196146 *
    197147 * @returns Pointer to allocated memory.
     
    202152 * @param   cbSize      Size of the block.
    203153 * @param   ppv         Where to store the pointer to the allocated memory on success.
    204  */
    205 VMMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
    206 {
    207     void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
     154 * @param   pR0Ptr      Where to return the ring-0 address of the memory.
     155 */
     156VMMR3DECL(int) MMR3UkHeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv, PRTR0PTR pR0Ptr)
     157{
     158    void *pv = mmR3UkHeapAlloc(pVM->pUVM->mm.s.pUkHeap, enmTag, cbSize, false, pR0Ptr);
    208159    if (pv)
    209160    {
     
    216167
    217168/**
    218  * Same as MMR3HeapAlloc() only the memory is zeroed.
    219  *
    220  * @returns Pointer to allocated memory.
    221  * @param   pUVM        Pointer to the user mode VM structure.
    222  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    223  *                      basis in addition to a global one. Thus we can easily
    224  *                      identify how memory is used by the VM.
    225  * @param   cbSize      Size of the block.
    226  */
    227 VMMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
    228 {
    229     return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
    230 }
    231 
    232 
    233 /**
    234  * Same as MMR3HeapAlloc() only the memory is zeroed.
     169 * Same as MMR3UkHeapAlloc() only the memory is zeroed.
    235170 *
    236171 * @returns Pointer to allocated memory.
     
    240175 *                      identify how memory is used by the VM.
    241176 * @param   cbSize      Size of the block.
    242  */
    243 VMMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
    244 {
    245     return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
    246 }
    247 
    248 
    249 /**
    250  * Same as MMR3HeapAllocZ().
    251  *
    252  * @returns Pointer to allocated memory.
    253  * @param   pUVM        Pointer to the user mode VM structure.
    254  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    255  *                      basis in addition to a global one. Thus we can easily
    256  *                      identify how memory is used by the VM.
    257  * @param   cbSize      Size of the block.
    258  * @param   ppv         Where to store the pointer to the allocated memory on success.
    259  */
    260 VMMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
    261 {
    262     Assert(pUVM->mm.s.pHeap);
    263     void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
    264     if (pv)
    265     {
    266         *ppv = pv;
    267         return VINF_SUCCESS;
    268     }
    269     return VERR_NO_MEMORY;
    270 }
    271 
    272 
    273 /**
    274  * Same as MMR3HeapAllocZ().
     177 * @param   pR0Ptr      Where to return the ring-0 address of the memory.
     178 */
     179VMMR3DECL(void *) MMR3UkHeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr)
     180{
     181    return mmR3UkHeapAlloc(pVM->pUVM->mm.s.pUkHeap, enmTag, cbSize, true, pR0Ptr);
     182}
     183
     184
     185/**
     186 * Same as MMR3UkHeapAllocZ().
    275187 *
    276188 * @returns Pointer to allocated memory.
     
    281193 * @param   cbSize      Size of the block.
    282194 * @param   ppv         Where to store the pointer to the allocated memory on success.
    283  */
    284 VMMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
    285 {
    286     void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
     195 * @param   pR0Ptr      Where to return the ring-0 address of the memory.
     196 */
     197VMMR3DECL(int) MMR3UkHeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv, PRTR0PTR pR0Ptr)
     198{
     199    void *pv = mmR3UkHeapAlloc(pVM->pUVM->mm.s.pUkHeap, enmTag, cbSize, true, pR0Ptr);
    287200    if (pv)
    288201    {
     
    291204    }
    292205    return VERR_NO_MEMORY;
     206}
     207
     208
     209/***
     210 * Worker for mmR3UkHeapAlloc that creates and adds a new sub-heap.
     211 *
     212 * @returns Pointer to the new sub-heap.
     213 * @param   pHeap       The heap
     214 * @param   cbSubHeap   The size of the sub-heap.
     215 */
     216static PMMUKHEAPSUB mmR3UkHeapAddSubHeap(PMMUKHEAP pHeap, size_t cbSubHeap)
     217{
     218    PMMUKHEAPSUB pSubHeap = (PMMUKHEAPSUB)MMR3HeapAllocU(pHeap->pUVM, MM_TAG_MM/*_UK_HEAP*/, sizeof(*pSubHeap));
     219    if (pSubHeap)
     220    {
     221        pSubHeap->cb = cbSubHeap;
     222        int rc = SUPR3PageAllocEx(pSubHeap->cb >> PAGE_SHIFT, 0, &pSubHeap->pv, &pSubHeap->pvR0, NULL);
     223        if (RT_SUCCESS(rc))
     224        {
     225            rc = RTHeapSimpleInit(&pSubHeap->hSimple, pSubHeap->pv, pSubHeap->cb);
     226            if (RT_SUCCESS(rc))
     227            {
     228                pSubHeap->pNext = pHeap->pSubHeapHead;
     229                pHeap->pSubHeapHead = pSubHeap;
     230                return pSubHeap;
     231            }
     232
     233            /* bail out */
     234            SUPR3PageFreeEx(pSubHeap->pv, pSubHeap->cb >> PAGE_SHIFT);
     235        }
     236        MMR3HeapFree(pSubHeap);
     237    }
     238    return NULL;
    293239}
    294240
     
    302248 *                      basis in addition to a global one. Thus we can easily
    303249 *                      identify how memory is used by the VM.
    304  * @param   cbSize      Size of the block.
     250 * @param   cb          Size of the block.
    305251 * @param   fZero       Whether or not to zero the memory block.
    306  */
    307 void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero)
    308 {
    309 #ifdef MMR3HEAP_WITH_STATISTICS
     252 * @param   pR0Ptr      Where to return the ring-0 pointer.
     253 */
     254static void *mmR3UkHeapAlloc(PMMUKHEAP pHeap, MMTAG enmTag, size_t cb, bool fZero, PRTR0PTR pR0Ptr)
     255{
     256    if (pR0Ptr)
     257        *pR0Ptr = NIL_RTR0PTR;
    310258    RTCritSectEnter(&pHeap->Lock);
    311259
     260#ifdef MMUKHEAP_WITH_STATISTICS
    312261    /*
    313262     * Find/alloc statistics nodes.
    314263     */
    315264    pHeap->Stat.cAllocations++;
    316     PMMHEAPSTAT pStat = (PMMHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);
     265    PMMUKHEAPSTAT pStat = (PMMUKHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);
    317266    if (pStat)
    318     {
    319267        pStat->cAllocations++;
    320 
    321         RTCritSectLeave(&pHeap->Lock);
    322     }
    323268    else
    324269    {
    325         pStat = (PMMHEAPSTAT)RTMemAllocZ(sizeof(MMHEAPSTAT));
     270        pStat = (PMMUKHEAPSTAT)MMR3HeapAllocZU(pHeap->pUVM, MM_TAG_MM, sizeof(MMUKHEAPSTAT));
    326271        if (!pStat)
    327272        {
     
    332277        }
    333278        pStat->Core.Key = (AVLULKEY)enmTag;
    334         pStat->pHeap    = pHeap;
    335279        RTAvlULInsert(&pHeap->pStatTree, &pStat->Core);
    336280
    337281        pStat->cAllocations++;
    338         RTCritSectLeave(&pHeap->Lock);
    339282
    340283        /* register the statistics */
    341284        PUVM pUVM = pHeap->pUVM;
    342285        const char *pszTag = mmR3GetTagName(enmTag);
    343         STAMR3RegisterFU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of bytes currently allocated.",    "/MM/R3Heap/%s", pszTag);
    344         STAMR3RegisterFU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.",        "/MM/R3Heap/%s/cAllocations", pszTag);
    345         STAMR3RegisterFU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.",      "/MM/R3Heap/%s/cReallocations", pszTag);
    346         STAMR3RegisterFU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.",         "/MM/R3Heap/%s/cFrees", pszTag);
    347         STAMR3RegisterFU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of failures.",                     "/MM/R3Heap/%s/cFailures", pszTag);
    348         STAMR3RegisterFU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes allocated.",        "/MM/R3Heap/%s/cbAllocated", pszTag);
    349         STAMR3RegisterFU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes freed.",            "/MM/R3Heap/%s/cbFreed", pszTag);
     286        STAMR3RegisterFU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of bytes currently allocated.",    "/MM/UkHeap/%s", pszTag);
     287        STAMR3RegisterFU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number or MMR3UkHeapAlloc() calls.",      "/MM/UkHeap/%s/cAllocations", pszTag);
     288        STAMR3RegisterFU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3UkHeapRealloc() calls.",    "/MM/UkHeap/%s/cReallocations", pszTag);
     289        STAMR3RegisterFU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_CALLS, "Number of MMR3UkHeapFree() calls.",       "/MM/UkHeap/%s/cFrees", pszTag);
     290        STAMR3RegisterFU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of failures.",                     "/MM/UkHeap/%s/cFailures", pszTag);
     291        STAMR3RegisterFU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes allocated.",        "/MM/UkHeap/%s/cbAllocated", pszTag);
     292        STAMR3RegisterFU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Total number of bytes freed.",            "/MM/UkHeap/%s/cbFreed", pszTag);
    350293    }
    351294#endif
     
    354297     * Validate input.
    355298     */
    356     if (cbSize == 0)
    357     {
    358 #ifdef MMR3HEAP_WITH_STATISTICS
    359         RTCritSectEnter(&pHeap->Lock);
     299    if (cb == 0)
     300    {
     301#ifdef MMUKHEAP_WITH_STATISTICS
    360302        pStat->cFailures++;
    361303        pHeap->Stat.cFailures++;
     304#endif
    362305        RTCritSectLeave(&pHeap->Lock);
    363 #endif
    364306        return NULL;
    365307    }
     
    368310     * Allocate heap block.
    369311     */
    370     cbSize = RT_ALIGN_Z(cbSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
    371     PMMHEAPHDR  pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize));
    372     if (!pHdr)
    373     {
    374         AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cbSize, enmTag, &enmTag));
    375 #ifdef MMR3HEAP_WITH_STATISTICS
    376         RTCritSectEnter(&pHeap->Lock);
    377         pStat->cFailures++;
    378         pHeap->Stat.cFailures++;
    379         RTCritSectLeave(&pHeap->Lock);
    380 #endif
    381         return NULL;
    382     }
    383     Assert(!((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)));
    384 
    385     RTCritSectEnter(&pHeap->Lock);
    386 
    387     /*
    388      * Init and link in the header.
    389      */
    390     pHdr->pNext = NULL;
    391     pHdr->pPrev = pHeap->pTail;
    392     if (pHdr->pPrev)
    393         pHdr->pPrev->pNext = pHdr;
    394     else
    395         pHeap->pHead = pHdr;
    396     pHeap->pTail = pHdr;
    397 #ifdef MMR3HEAP_WITH_STATISTICS
    398     pHdr->pStat  = pStat;
    399 #else
    400     pHdr->pStat  = &pHeap->Stat;
    401 #endif
    402     pHdr->cbSize = cbSize;
     312    cb = RT_ALIGN_Z(cb, MMUKHEAP_SIZE_ALIGNMENT);
     313    void *pv = NULL;
     314    PMMUKHEAPSUB pSubHeapPrev = NULL;
     315    PMMUKHEAPSUB pSubHeap = pHeap->pSubHeapHead;
     316    while (pSubHeap)
     317    {
     318        if (fZero)
     319            pv = RTHeapSimpleAllocZ(pSubHeap->hSimple, cb, MMUKHEAP_SIZE_ALIGNMENT);
     320        else
     321            pv = RTHeapSimpleAlloc(pSubHeap->hSimple, cb, MMUKHEAP_SIZE_ALIGNMENT);
     322        if (pv)
     323        {
     324            /* Move the sub-heap with free memory to the head. */
     325            if (pSubHeapPrev)
     326            {
     327                pSubHeapPrev->pNext = pSubHeap->pNext;
     328                pSubHeap->pNext = pHeap->pSubHeapHead;
     329                pHeap->pSubHeapHead = pSubHeap;
     330            }
     331            break;
     332        }
     333        pSubHeapPrev = pSubHeap;
     334        pSubHeap = pSubHeap->pNext;
     335    }
     336    if (RT_UNLIKELY(!pv))
     337    {
     338        /*
     339         * Add another sub-heap.
     340         */
     341        pSubHeap = mmR3UkHeapAddSubHeap(pHeap, RT_MAX(RT_ALIGN_Z(cb, PAGE_SIZE) + PAGE_SIZE * 16, _256K));
     342        if (pSubHeap)
     343        {
     344            if (fZero)
     345                pv = RTHeapSimpleAllocZ(pSubHeap->hSimple, cb, MMUKHEAP_SIZE_ALIGNMENT);
     346            else
     347                pv = RTHeapSimpleAlloc(pSubHeap->hSimple, cb, MMUKHEAP_SIZE_ALIGNMENT);
     348        }
     349        if (RT_UNLIKELY(!pv))
     350        {
     351            AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cb, enmTag, &enmTag));
     352#ifdef MMUKHEAP_WITH_STATISTICS
     353            pStat->cFailures++;
     354            pHeap->Stat.cFailures++;
     355#endif
     356            RTCritSectLeave(&pHeap->Lock);
     357            return NULL;
     358        }
     359    }
    403360
    404361    /*
    405362     * Update statistics
    406363     */
    407 #ifdef MMR3HEAP_WITH_STATISTICS
    408     pStat->cbAllocated          += cbSize;
    409     pStat->cbCurAllocated       += cbSize;
    410     pHeap->Stat.cbAllocated     += cbSize;
    411     pHeap->Stat.cbCurAllocated  += cbSize;
    412 #endif
    413 
     364#ifdef MMUKHEAP_WITH_STATISTICS
     365    size_t cbActual = RTHeapSimpleSize(pSubHeap->hSimple, pv);
     366    pStat->cbAllocated          += cbActual;
     367    pStat->cbCurAllocated       += cbActual;
     368    pHeap->Stat.cbAllocated     += cbActual;
     369    pHeap->Stat.cbCurAllocated  += cbActual;
     370#endif
     371
     372    if (pR0Ptr)
     373        *pR0Ptr = (uintptr_t)pv - (uintptr_t)pSubHeap->pv + pSubHeap->pvR0;
    414374    RTCritSectLeave(&pHeap->Lock);
    415 
    416     return pHdr + 1;
    417 }
    418 
    419 
    420 /**
    421  * Reallocate memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
    422  *
    423  * @returns Pointer to reallocated memory.
    424  * @param   pv          Pointer to the memory block to reallocate.
    425  *                      Must not be NULL!
    426  * @param   cbNewSize   New block size.
    427  */
    428 VMMR3DECL(void *) MMR3HeapRealloc(void *pv, size_t cbNewSize)
    429 {
    430     AssertMsg(pv, ("Invalid pointer pv=%p\n", pv));
    431     if (!pv)
    432         return NULL;
    433 
    434     /*
    435      * If newsize is zero then this is a free.
    436      */
    437     if (!cbNewSize)
    438     {
    439         MMR3HeapFree(pv);
    440         return NULL;
    441     }
    442 
    443     /*
    444      * Validate header.
    445      */
    446     PMMHEAPHDR  pHdr = (PMMHEAPHDR)pv - 1;
    447     if (    pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
    448         ||  (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
    449     {
    450         AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
    451         return NULL;
    452     }
    453     Assert(pHdr->pStat != NULL);
    454     Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
    455     Assert(!((uintptr_t)pHdr->pPrev & (RTMEM_ALIGNMENT - 1)));
    456 
    457     PMMHEAP pHeap = pHdr->pStat->pHeap;
    458 
    459 #ifdef MMR3HEAP_WITH_STATISTICS
    460     RTCritSectEnter(&pHeap->Lock);
    461     pHdr->pStat->cReallocations++;
    462     pHeap->Stat.cReallocations++;
    463     RTCritSectLeave(&pHeap->Lock);
    464 #endif
    465 
    466     /*
    467      * Rellocate the block.
    468      */
    469     cbNewSize = RT_ALIGN_Z(cbNewSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
    470     PMMHEAPHDR pHdrNew = (PMMHEAPHDR)RTMemRealloc(pHdr, cbNewSize);
    471     if (!pHdrNew)
    472     {
    473 #ifdef MMR3HEAP_WITH_STATISTICS
    474         RTCritSectEnter(&pHeap->Lock);
    475         pHdr->pStat->cFailures++;
    476         pHeap->Stat.cFailures++;
    477         RTCritSectLeave(&pHeap->Lock);
    478 #endif
    479         return NULL;
    480     }
    481 
    482     /*
    483      * Update pointers.
    484      */
    485     if (pHdrNew != pHdr)
    486     {
    487         RTCritSectEnter(&pHeap->Lock);
    488         if (pHdrNew->pPrev)
    489             pHdrNew->pPrev->pNext = pHdrNew;
    490         else
    491             pHeap->pHead = pHdrNew;
    492 
    493         if (pHdrNew->pNext)
    494             pHdrNew->pNext->pPrev = pHdrNew;
    495         else
    496             pHeap->pTail = pHdrNew;
    497         RTCritSectLeave(&pHeap->Lock);
    498     }
    499 
    500     /*
    501      * Update statistics.
    502      */
    503 #ifdef MMR3HEAP_WITH_STATISTICS
    504     RTCritSectEnter(&pHeap->Lock);
    505     pHdrNew->pStat->cbAllocated += cbNewSize - pHdrNew->cbSize;
    506     pHeap->Stat.cbAllocated += cbNewSize - pHdrNew->cbSize;
    507     RTCritSectLeave(&pHeap->Lock);
    508 #endif
    509 
    510     pHdrNew->cbSize = cbNewSize;
    511 
    512     return pHdrNew + 1;
    513 }
    514 
    515 
    516 /**
    517  * Duplicates the specified string.
    518  *
    519  * @returns Pointer to the duplicate.
    520  * @returns NULL on failure or when input NULL.
    521  * @param   pUVM        Pointer to the user mode VM structure.
    522  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    523  *                      basis in addition to a global one. Thus we can easily
    524  *                      identify how memory is used by the VM.
    525  * @param   psz         The string to duplicate. NULL is allowed.
    526  */
    527 VMMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz)
    528 {
    529     if (!psz)
    530         return NULL;
    531     AssertPtr(psz);
    532 
    533     size_t cch = strlen(psz) + 1;
    534     char *pszDup = (char *)MMR3HeapAllocU(pUVM, enmTag, cch);
    535     if (pszDup)
    536         memcpy(pszDup, psz, cch);
    537     return pszDup;
    538 }
    539 
    540 
    541 /**
    542  * Duplicates the specified string.
    543  *
    544  * @returns Pointer to the duplicate.
    545  * @returns NULL on failure or when input NULL.
     375    return pv;
     376}
     377
     378
     379/**
     380 * Releases memory allocated with MMR3UkHeapAlloc() and MMR3UkHeapAllocZ()
     381 *
    546382 * @param   pVM         The VM handle.
    547  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    548  *                      basis in addition to a global one. Thus we can easily
    549  *                      identify how memory is used by the VM.
    550  * @param   psz         The string to duplicate. NULL is allowed.
    551  */
    552 VMMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz)
    553 {
    554     return MMR3HeapStrDupU(pVM->pUVM, enmTag, psz);
    555 }
    556 
    557 
    558 /**
    559  * Allocating string printf.
    560  *
    561  * @returns Pointer to the string.
    562  * @param   pVM         The VM
    563  * @param   enmTag      The statistics tag.
    564  * @param   pszFormat   The format string.
    565  * @param   ...         Format arguments.
    566  */
    567 VMMR3DECL(char *)    MMR3HeapAPrintf(PVM pVM, MMTAG enmTag, const char *pszFormat, ...)
    568 {
    569     va_list va;
    570     va_start(va, pszFormat);
    571     char *psz = MMR3HeapAPrintfVU(pVM->pUVM, enmTag, pszFormat, va);
    572     va_end(va);
    573     return psz;
    574 }
    575 
    576 
    577 /**
    578  * Allocating string printf.
    579  *
    580  * @returns Pointer to the string.
    581  * @param   pUVM        Pointer to the user mode VM structure.
    582  * @param   enmTag      The statistics tag.
    583  * @param   pszFormat   The format string.
    584  * @param   ...         Format arguments.
    585  */
    586 VMMR3DECL(char *)    MMR3HeapAPrintfU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, ...)
    587 {
    588     va_list va;
    589     va_start(va, pszFormat);
    590     char *psz = MMR3HeapAPrintfVU(pUVM, enmTag, pszFormat, va);
    591     va_end(va);
    592     return psz;
    593 }
    594 
    595 
    596 /**
    597  * Allocating string printf.
    598  *
    599  * @returns Pointer to the string.
    600  * @param   pVM         The VM
    601  * @param   enmTag      The statistics tag.
    602  * @param   pszFormat   The format string.
    603  * @param   va          Format arguments.
    604  */
    605 VMMR3DECL(char *)    MMR3HeapAPrintfV(PVM pVM, MMTAG enmTag, const char *pszFormat, va_list va)
    606 {
    607     return MMR3HeapAPrintfVU(pVM->pUVM, enmTag, pszFormat, va);
    608 }
    609 
    610 
    611 /**
    612  * Allocating string printf.
    613  *
    614  * @returns Pointer to the string.
    615  * @param   pUVM        Pointer to the user mode VM structure.
    616  * @param   enmTag      The statistics tag.
    617  * @param   pszFormat   The format string.
    618  * @param   va          Format arguments.
    619  */
    620 VMMR3DECL(char *)    MMR3HeapAPrintfVU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, va_list va)
    621 {
    622     /*
    623      * The lazy bird way.
    624      */
    625     char *psz;
    626     int cch = RTStrAPrintfV(&psz, pszFormat, va);
    627     if (cch < 0)
    628         return NULL;
    629     Assert(psz[cch] == '\0');
    630     char *pszRet = (char *)MMR3HeapAllocU(pUVM, enmTag, cch + 1);
    631     if (pszRet)
    632         memcpy(pszRet, psz, cch + 1);
    633     RTStrFree(psz);
    634     return pszRet;
    635 }
    636 
    637 
    638 /**
    639  * Releases memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
    640  *
    641383 * @param   pv          Pointer to the memory block to free.
    642384 */
    643 VMMR3DECL(void) MMR3HeapFree(void *pv)
     385VMMR3DECL(void) MMR3UkHeapFree(PVM pVM, void *pv, MMTAG enmTag)
    644386{
    645387    /* Ignore NULL pointers. */
     
    647389        return;
    648390
    649     /*
    650      * Validate header.
    651      */
    652     PMMHEAPHDR  pHdr = (PMMHEAPHDR)pv - 1;
    653     if (    pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
    654         ||  (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
    655     {
    656         AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
    657         return;
    658     }
    659     Assert(pHdr->pStat != NULL);
    660     Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
    661     Assert(!((uintptr_t)pHdr->pPrev & (RTMEM_ALIGNMENT - 1)));
    662 
    663     /*
    664      * Update statistics
    665      */
    666     PMMHEAP pHeap = pHdr->pStat->pHeap;
     391    PMMUKHEAP pHeap = pVM->pUVM->mm.s.pUkHeap;
    667392    RTCritSectEnter(&pHeap->Lock);
    668393
    669 #ifdef MMR3HEAP_WITH_STATISTICS
    670     pHdr->pStat->cFrees++;
    671     pHeap->Stat.cFrees++;
    672     pHdr->pStat->cbFreed            += pHdr->cbSize;
    673     pHeap->Stat.cbFreed             += pHdr->cbSize;
    674     pHdr->pStat->cbCurAllocated     -= pHdr->cbSize;
    675     pHeap->Stat.cbCurAllocated      -= pHdr->cbSize;
    676 #endif
    677 
    678     /*
    679      * Unlink it.
    680      */
    681     if (pHdr->pPrev)
    682         pHdr->pPrev->pNext = pHdr->pNext;
    683     else
    684         pHeap->pHead = pHdr->pNext;
    685 
    686     if (pHdr->pNext)
    687         pHdr->pNext->pPrev = pHdr->pPrev;
    688     else
    689         pHeap->pTail = pHdr->pPrev;
    690 
    691     RTCritSectLeave(&pHeap->Lock);
    692 
    693     /*
    694      * Free the memory.
    695      */
    696     RTMemFree(pHdr);
    697 }
    698 
    699 
    700 /**
    701  * Gets the string name of a memory tag.
    702  *
    703  * @returns name of enmTag.
    704  * @param   enmTag      The tag.
    705  */
    706 const char *mmR3GetTagName(MMTAG enmTag)
    707 {
    708     switch (enmTag)
    709     {
    710         #define TAG2STR(tag) case MM_TAG_##tag: return #tag
    711 
    712         TAG2STR(CFGM);
    713         TAG2STR(CFGM_BYTES);
    714         TAG2STR(CFGM_STRING);
    715         TAG2STR(CFGM_USER);
    716 
    717         TAG2STR(CSAM);
    718         TAG2STR(CSAM_PATCH);
    719 
    720         TAG2STR(DBGF);
    721         TAG2STR(DBGF_INFO);
    722         TAG2STR(DBGF_LINE);
    723         TAG2STR(DBGF_LINE_DUP);
    724         TAG2STR(DBGF_MODULE);
    725         TAG2STR(DBGF_OS);
    726         TAG2STR(DBGF_STACK);
    727         TAG2STR(DBGF_SYMBOL);
    728         TAG2STR(DBGF_SYMBOL_DUP);
    729 
    730         TAG2STR(EM);
    731 
    732         TAG2STR(IOM);
    733         TAG2STR(IOM_STATS);
    734 
    735         TAG2STR(MM);
    736         TAG2STR(MM_LOOKUP_GUEST);
    737         TAG2STR(MM_LOOKUP_PHYS);
    738         TAG2STR(MM_LOOKUP_VIRT);
    739         TAG2STR(MM_PAGE);
    740 
    741         TAG2STR(PARAV);
    742 
    743         TAG2STR(PATM);
    744         TAG2STR(PATM_PATCH);
    745 
    746         TAG2STR(PDM);
    747         TAG2STR(PDM_DEVICE);
    748         TAG2STR(PDM_DEVICE_USER);
    749         TAG2STR(PDM_DRIVER);
    750         TAG2STR(PDM_DRIVER_USER);
    751         TAG2STR(PDM_USB);
    752         TAG2STR(PDM_USB_USER);
    753         TAG2STR(PDM_LUN);
    754         TAG2STR(PDM_QUEUE);
    755         TAG2STR(PDM_THREAD);
    756         TAG2STR(PDM_ASYNC_COMPLETION);
    757 
    758         TAG2STR(PGM);
    759         TAG2STR(PGM_CHUNK_MAPPING);
    760         TAG2STR(PGM_HANDLERS);
    761         TAG2STR(PGM_MAPPINGS);
    762         TAG2STR(PGM_PHYS);
    763         TAG2STR(PGM_POOL);
    764 
    765         TAG2STR(REM);
    766 
    767         TAG2STR(SELM);
    768 
    769         TAG2STR(SSM);
    770 
    771         TAG2STR(STAM);
    772 
    773         TAG2STR(TM);
    774 
    775         TAG2STR(TRPM);
    776 
    777         TAG2STR(VM);
    778         TAG2STR(VM_REQ);
    779 
    780         TAG2STR(VMM);
    781 
    782         TAG2STR(HWACCM);
    783 
    784         #undef TAG2STR
    785 
    786         default:
    787         {
    788             AssertMsgFailed(("Unknown tag %d! forgot to add it to the switch?\n", enmTag));
    789             static char sz[48];
    790             RTStrPrintf(sz, sizeof(sz), "%d", enmTag);
    791             return sz;
    792         }
    793     }
    794 }
    795 
     394    /*
     395     * Find the sub-heap and block
     396     */
     397#ifdef MMUKHEAP_WITH_STATISTICS
     398    size_t cbActual = 0;
     399#endif
     400    PMMUKHEAPSUB pSubHeap = pHeap->pSubHeapHead;
     401    while (pSubHeap)
     402    {
     403        if ((uintptr_t)pv - (uintptr_t)pSubHeap->pv < pSubHeap->cb)
     404        {
     405#ifdef MMUKHEAP_WITH_STATISTICS
     406            cbActual = RTHeapSimpleSize(pSubHeap->hSimple, pv);
     407            PMMUKHEAPSTAT pStat = (PMMUKHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);
     408            if (pStat)
     409            {
     410                pStat->cFrees++;
     411                pStat->cbCurAllocated     -= cbActual;
     412                pStat->cbFreed            += cbActual;
     413            }
     414            pHeap->Stat.cFrees++;
     415            pHeap->Stat.cbFreed           += cbActual;
     416            pHeap->Stat.cbCurAllocated    -= cbActual;
     417#endif
     418            RTHeapSimpleFree(pSubHeap->hSimple, pv);
     419
     420            RTCritSectLeave(&pHeap->Lock);
     421            return;
     422        }
     423    }
     424    AssertMsgFailed(("pv=%p\n", pv));
     425}
     426
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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