vbox的更動 18792 路徑 trunk/src/VBox/VMM/MMUkHeap.cpp
- 時間撮記:
- 2009-4-6 下午06:40:52 (16 年 以前)
- 檔案:
-
- 複製 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/VMM/MMUkHeap.cpp
-
屬性 svn:keywords
由
Id
變更至Author Date Id Revision
r18763 r18792 1 1 /* $Id$ */ 2 2 /** @file 3 * MM - Memory Manager - Heap.3 * MM - Memory Manager - Ring-3 Heap with kernel accessible mapping. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.7 * Copyright (C) 2006-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 27 27 #include <VBox/mm.h> 28 28 #include <VBox/stam.h> 29 #include <VBox/pgm.h>30 29 #include "MMInternal.h" 31 30 #include <VBox/vm.h> … … 35 34 #include <VBox/log.h> 36 35 37 #include <iprt/alloc.h>38 36 #include <iprt/assert.h> 39 37 #include <iprt/string.h> 38 #include <iprt/heap.h> 40 39 41 40 … … 43 42 * Internal Functions * 44 43 *******************************************************************************/ 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. 44 static 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. 51 53 * 52 54 * @returns VBox status. … … 54 56 * @param ppHeap Where to store the heap pointer. 55 57 */ 56 int mmR3 HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap)57 { 58 PMM HEAP pHeap = (PMMHEAP)RTMemAllocZ(sizeof(MMHEAP) + sizeof(MMHEAPSTAT));58 int mmR3UkHeapCreateU(PUVM pUVM, PMMUKHEAP *ppHeap) 59 { 60 PMMUKHEAP pHeap = (PMMUKHEAP)MMR3HeapAllocZU(pUVM, MM_TAG_MM, sizeof(MMUKHEAP)); 59 61 if (pHeap) 60 62 { … … 66 68 */ 67 69 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."); 75 76 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."); 79 80 #endif 80 81 *ppHeap = pHeap; … … 82 83 } 83 84 AssertRC(rc); 84 RTMemFree(pHeap);85 MMR3HeapFree(pHeap); 85 86 } 86 87 AssertMsgFailed(("failed to allocate heap structure\n")); … … 90 91 91 92 /** 92 * Destroy a heap.93 * Destroy a User-kernel heap. 93 94 * 94 95 * @param pHeap Heap handle. 95 96 */ 96 void mmR3 HeapDestroy(PMMHEAP pHeap)97 void mmR3UkHeapDestroy(PMMUKHEAP pHeap) 97 98 { 98 99 /* … … 103 104 104 105 /* 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); 144 117 } 145 118 … … 161 134 * identify how memory is used by the VM. 162 135 * @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 */ 138 VMMR3DECL(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(). 196 146 * 197 147 * @returns Pointer to allocated memory. … … 202 152 * @param cbSize Size of the block. 203 153 * @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 */ 156 VMMR3DECL(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); 208 159 if (pv) 209 160 { … … 216 167 217 168 /** 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. 235 170 * 236 171 * @returns Pointer to allocated memory. … … 240 175 * identify how memory is used by the VM. 241 176 * @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 */ 179 VMMR3DECL(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(). 275 187 * 276 188 * @returns Pointer to allocated memory. … … 281 193 * @param cbSize Size of the block. 282 194 * @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 */ 197 VMMR3DECL(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); 287 200 if (pv) 288 201 { … … 291 204 } 292 205 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 */ 216 static 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; 293 239 } 294 240 … … 302 248 * basis in addition to a global one. Thus we can easily 303 249 * identify how memory is used by the VM. 304 * @param cb SizeSize of the block.250 * @param cb Size of the block. 305 251 * @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 */ 254 static void *mmR3UkHeapAlloc(PMMUKHEAP pHeap, MMTAG enmTag, size_t cb, bool fZero, PRTR0PTR pR0Ptr) 255 { 256 if (pR0Ptr) 257 *pR0Ptr = NIL_RTR0PTR; 310 258 RTCritSectEnter(&pHeap->Lock); 311 259 260 #ifdef MMUKHEAP_WITH_STATISTICS 312 261 /* 313 262 * Find/alloc statistics nodes. 314 263 */ 315 264 pHeap->Stat.cAllocations++; 316 PMM HEAPSTAT pStat = (PMMHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);265 PMMUKHEAPSTAT pStat = (PMMUKHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag); 317 266 if (pStat) 318 {319 267 pStat->cAllocations++; 320 321 RTCritSectLeave(&pHeap->Lock);322 }323 268 else 324 269 { 325 pStat = (PMM HEAPSTAT)RTMemAllocZ(sizeof(MMHEAPSTAT));270 pStat = (PMMUKHEAPSTAT)MMR3HeapAllocZU(pHeap->pUVM, MM_TAG_MM, sizeof(MMUKHEAPSTAT)); 326 271 if (!pStat) 327 272 { … … 332 277 } 333 278 pStat->Core.Key = (AVLULKEY)enmTag; 334 pStat->pHeap = pHeap;335 279 RTAvlULInsert(&pHeap->pStatTree, &pStat->Core); 336 280 337 281 pStat->cAllocations++; 338 RTCritSectLeave(&pHeap->Lock);339 282 340 283 /* register the statistics */ 341 284 PUVM pUVM = pHeap->pUVM; 342 285 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 MMR3 HeapAlloc() calls.", "/MM/R3Heap/%s/cAllocations", pszTag);345 STAMR3RegisterFU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Number of MMR3 HeapRealloc() calls.", "/MM/R3Heap/%s/cReallocations", pszTag);346 STAMR3RegisterFU(pUVM, &pStat->cFrees, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, STAMUNIT_CALLS, "Number of MMR3 HeapFree() 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); 350 293 } 351 294 #endif … … 354 297 * Validate input. 355 298 */ 356 if (cbSize == 0) 357 { 358 #ifdef MMR3HEAP_WITH_STATISTICS 359 RTCritSectEnter(&pHeap->Lock); 299 if (cb == 0) 300 { 301 #ifdef MMUKHEAP_WITH_STATISTICS 360 302 pStat->cFailures++; 361 303 pHeap->Stat.cFailures++; 304 #endif 362 305 RTCritSectLeave(&pHeap->Lock); 363 #endif364 306 return NULL; 365 307 } … … 368 310 * Allocate heap block. 369 311 */ 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 } 403 360 404 361 /* 405 362 * Update statistics 406 363 */ 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; 414 374 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 * 546 382 * @param pVM The VM handle. 547 * @param enmTag Statistics tag. Statistics are collected on a per tag548 * basis in addition to a global one. Thus we can easily549 * 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 VM563 * @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 VM601 * @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 *641 383 * @param pv Pointer to the memory block to free. 642 384 */ 643 VMMR3DECL(void) MMR3 HeapFree(void *pv)385 VMMR3DECL(void) MMR3UkHeapFree(PVM pVM, void *pv, MMTAG enmTag) 644 386 { 645 387 /* Ignore NULL pointers. */ … … 647 389 return; 648 390 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; 667 392 RTCritSectEnter(&pHeap->Lock); 668 393 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 -
屬性 svn:keywords
由
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器