VirtualBox

source: vbox/trunk/src/VBox/VMM/MMHeap.cpp@ 6862

Last change on this file since 6862 was 6818, checked in by vboxsync, 17 years ago

New tag: MM_TAG_PGM_PHYS.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.7 KB
Line 
1/* $Id: MMHeap.cpp 6818 2008-02-05 21:52:12Z vboxsync $ */
2/** @file
3 * MM - Memory Monitor(/Manager) - Heap.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_MM_HEAP
23#include <VBox/mm.h>
24#include <VBox/stam.h>
25#include <VBox/pgm.h>
26#include "MMInternal.h"
27#include <VBox/vm.h>
28#include <VBox/uvm.h>
29#include <VBox/err.h>
30#include <VBox/param.h>
31#include <VBox/log.h>
32
33#include <iprt/alloc.h>
34#include <iprt/assert.h>
35#include <iprt/string.h>
36
37
38/*******************************************************************************
39* Internal Functions *
40*******************************************************************************/
41static void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero);
42
43
44
45/**
46 * Allocate and initialize a heap structure and it's associated substructures.
47 *
48 * @returns VBox status.
49 * @param pVM The handle to the VM the heap should be associated with.
50 * @param ppHeap Where to store the heap pointer.
51 */
52int mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap)
53{
54 PMMHEAP pHeap = (PMMHEAP)RTMemAllocZ(sizeof(MMHEAP) + sizeof(MMHEAPSTAT));
55 if (pHeap)
56 {
57 int rc = RTCritSectInit(&pHeap->Lock);
58 if (VBOX_SUCCESS(rc))
59 {
60 /*
61 * Initialize the global stat record.
62 */
63 pHeap->pUVM = pUVM;
64 pHeap->Stat.pHeap = pHeap;
65#ifdef MMR3HEAP_WITH_STATISTICS
66 PMMHEAPSTAT pStat = &pHeap->Stat;
67 STAMR3RegisterU(pUVM, &pStat->cAllocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cAllocations", STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
68 STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cReallocations", STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
69 STAMR3RegisterU(pUVM, &pStat->cFrees, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFrees", STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
70 STAMR3RegisterU(pUVM, &pStat->cFailures, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFailures", STAMUNIT_COUNT, "Number of failures.");
71 STAMR3RegisterU(pUVM, &pStat->cbCurAllocated, sizeof(pStat->cbCurAllocated) == sizeof(uint32_t) ? STAMTYPE_U32 : STAMTYPE_U64,
72 STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbCurAllocated", STAMUNIT_BYTES, "Number of bytes currently allocated.");
73 STAMR3RegisterU(pUVM, &pStat->cbAllocated, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbAllocated", STAMUNIT_BYTES, "Total number of bytes allocated.");
74 STAMR3RegisterU(pUVM, &pStat->cbFreed, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbFreed", STAMUNIT_BYTES, "Total number of bytes freed.");
75#endif
76 *ppHeap = pHeap;
77 return VINF_SUCCESS;
78 }
79 AssertRC(rc);
80 RTMemFree(pHeap);
81 }
82 AssertMsgFailed(("failed to allocate heap structure\n"));
83 return VERR_NO_MEMORY;
84}
85
86
87/**
88 * Destroy a heap.
89 *
90 * @param pHeap Heap handle.
91 */
92void mmR3HeapDestroy(PMMHEAP pHeap)
93{
94 /*
95 * Start by deleting the lock, that'll trap anyone
96 * attempting to use the heap.
97 */
98 RTCritSectDelete(&pHeap->Lock);
99
100 /*
101 * Walk the node list and free all the memory.
102 */
103 PMMHEAPHDR pHdr = pHeap->pHead;
104 while (pHdr)
105 {
106 void *pv = pHdr;
107 pHdr = pHdr->pNext;
108 RTMemFree(pv);
109 }
110
111 /*
112 * Free the stat nodes.
113 */
114 /** @todo free all nodes in a AVL tree. */
115 RTMemFree(pHeap);
116}
117
118
119/**
120 * Allocate memory associating it with the VM for collective cleanup.
121 *
122 * The memory will be allocated from the default heap but a header
123 * is added in which we keep track of which VM it belongs to and chain
124 * all the allocations together so they can be freed in one go.
125 *
126 * This interface is typically used for memory block which will not be
127 * freed during the life of the VM.
128 *
129 * @returns Pointer to allocated memory.
130 * @param pUVM Pointer to the user mode VM structure.
131 * @param enmTag Statistics tag. Statistics are collected on a per tag
132 * basis in addition to a global one. Thus we can easily
133 * identify how memory is used by the VM.
134 * @param cbSize Size of the block.
135 */
136MMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
137{
138 Assert(pUVM->mm.s.pHeap);
139 return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
140}
141
142
143/**
144 * Allocate memory associating it with the VM for collective cleanup.
145 *
146 * The memory will be allocated from the default heap but a header
147 * is added in which we keep track of which VM it belongs to and chain
148 * all the allocations together so they can be freed in one go.
149 *
150 * This interface is typically used for memory block which will not be
151 * freed during the life of the VM.
152 *
153 * @returns Pointer to allocated memory.
154 * @param pVM VM handle.
155 * @param enmTag Statistics tag. Statistics are collected on a per tag
156 * basis in addition to a global one. Thus we can easily
157 * identify how memory is used by the VM.
158 * @param cbSize Size of the block.
159 */
160MMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize)
161{
162 return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
163}
164
165
166/**
167 * Same as MMR3HeapAllocU().
168 *
169 * @returns Pointer to allocated memory.
170 * @param pUVM Pointer to the user mode VM structure.
171 * @param enmTag Statistics tag. Statistics are collected on a per tag
172 * basis in addition to a global one. Thus we can easily
173 * identify how memory is used by the VM.
174 * @param cbSize Size of the block.
175 * @param ppv Where to store the pointer to the allocated memory on success.
176 */
177MMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
178{
179 Assert(pUVM->mm.s.pHeap);
180 void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
181 if (pv)
182 {
183 *ppv = pv;
184 return VINF_SUCCESS;
185 }
186 return VERR_NO_MEMORY;
187}
188
189
190/**
191 * Same as MMR3HeapAlloc().
192 *
193 * @returns Pointer to allocated memory.
194 * @param pVM VM handle.
195 * @param enmTag Statistics tag. Statistics are collected on a per tag
196 * basis in addition to a global one. Thus we can easily
197 * identify how memory is used by the VM.
198 * @param cbSize Size of the block.
199 * @param ppv Where to store the pointer to the allocated memory on success.
200 */
201MMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
202{
203 void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
204 if (pv)
205 {
206 *ppv = pv;
207 return VINF_SUCCESS;
208 }
209 return VERR_NO_MEMORY;
210}
211
212
213/**
214 * Same as MMR3HeapAlloc() only the memory is zeroed.
215 *
216 * @returns Pointer to allocated memory.
217 * @param pUVM Pointer to the user mode VM structure.
218 * @param enmTag Statistics tag. Statistics are collected on a per tag
219 * basis in addition to a global one. Thus we can easily
220 * identify how memory is used by the VM.
221 * @param cbSize Size of the block.
222 */
223MMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
224{
225 return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
226}
227
228
229/**
230 * Same as MMR3HeapAlloc() only the memory is zeroed.
231 *
232 * @returns Pointer to allocated memory.
233 * @param pVM VM handle.
234 * @param enmTag Statistics tag. Statistics are collected on a per tag
235 * basis in addition to a global one. Thus we can easily
236 * identify how memory is used by the VM.
237 * @param cbSize Size of the block.
238 */
239MMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
240{
241 return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
242}
243
244
245/**
246 * Same as MMR3HeapAllocZ().
247 *
248 * @returns Pointer to allocated memory.
249 * @param pUVM Pointer to the user mode VM structure.
250 * @param enmTag Statistics tag. Statistics are collected on a per tag
251 * basis in addition to a global one. Thus we can easily
252 * identify how memory is used by the VM.
253 * @param cbSize Size of the block.
254 * @param ppv Where to store the pointer to the allocated memory on success.
255 */
256MMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
257{
258 Assert(pUVM->mm.s.pHeap);
259 void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
260 if (pv)
261 {
262 *ppv = pv;
263 return VINF_SUCCESS;
264 }
265 return VERR_NO_MEMORY;
266}
267
268
269/**
270 * Same as MMR3HeapAllocZ().
271 *
272 * @returns Pointer to allocated memory.
273 * @param pVM VM handle.
274 * @param enmTag Statistics tag. Statistics are collected on a per tag
275 * basis in addition to a global one. Thus we can easily
276 * identify how memory is used by the VM.
277 * @param cbSize Size of the block.
278 * @param ppv Where to store the pointer to the allocated memory on success.
279 */
280MMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
281{
282 void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
283 if (pv)
284 {
285 *ppv = pv;
286 return VINF_SUCCESS;
287 }
288 return VERR_NO_MEMORY;
289}
290
291
292/**
293 * Allocate memory from the heap.
294 *
295 * @returns Pointer to allocated memory.
296 * @param pHeap Heap handle.
297 * @param enmTag Statistics tag. Statistics are collected on a per tag
298 * basis in addition to a global one. Thus we can easily
299 * identify how memory is used by the VM.
300 * @param cbSize Size of the block.
301 * @param fZero Whether or not to zero the memory block.
302 */
303void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero)
304{
305#ifdef MMR3HEAP_WITH_STATISTICS
306 RTCritSectEnter(&pHeap->Lock);
307
308 /*
309 * Find/alloc statistics nodes.
310 */
311 pHeap->Stat.cAllocations++;
312 PMMHEAPSTAT pStat = (PMMHEAPSTAT)RTAvlULGet(&pHeap->pStatTree, (AVLULKEY)enmTag);
313 if (pStat)
314 {
315 pStat->cAllocations++;
316
317 RTCritSectLeave(&pHeap->Lock);
318 }
319 else
320 {
321 pStat = (PMMHEAPSTAT)RTMemAllocZ(sizeof(MMHEAPSTAT));
322 if (!pStat)
323 {
324 pHeap->Stat.cFailures++;
325 AssertMsgFailed(("Failed to allocate heap stat record.\n"));
326 RTCritSectLeave(&pHeap->Lock);
327 return NULL;
328 }
329 pStat->Core.Key = (AVLULKEY)enmTag;
330 pStat->pHeap = pHeap;
331 RTAvlULInsert(&pHeap->pStatTree, &pStat->Core);
332
333 pStat->cAllocations++;
334 RTCritSectLeave(&pHeap->Lock);
335
336 /* register the statistics */
337 PUVM pUVM = pHeap->pUVM;
338 char szName[80];
339 const char *pszTag = mmR3GetTagName(enmTag);
340 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cAllocations", pszTag);
341 STAMR3RegisterU(pUVM, &pStat->cAllocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
342
343 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cReallocations", pszTag);
344 STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
345
346 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cFrees", pszTag);
347 STAMR3RegisterU(pUVM, &pStat->cFrees, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
348
349 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cFailures", pszTag);
350 STAMR3RegisterU(pUVM, &pStat->cFailures, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_COUNT, "Number of failures.");
351
352 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbCurAllocated", pszTag);
353 STAMR3RegisterU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_BYTES, "Number of bytes currently allocated.");
354
355 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbAllocated", pszTag);
356 STAMR3RegisterU(pUVM, &pStat->cbAllocated, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_BYTES, "Total number of bytes allocated.");
357
358 RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbFreed", pszTag);
359 STAMR3RegisterU(pUVM, &pStat->cbFreed, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_BYTES, "Total number of bytes freed.");
360 }
361#endif
362
363 /*
364 * Validate input.
365 */
366 if (cbSize == 0)
367 {
368#ifdef MMR3HEAP_WITH_STATISTICS
369 RTCritSectEnter(&pHeap->Lock);
370 pStat->cFailures++;
371 pHeap->Stat.cFailures++;
372 RTCritSectLeave(&pHeap->Lock);
373#endif
374 return NULL;
375 }
376
377 /*
378 * Allocate heap block.
379 */
380 cbSize = RT_ALIGN_Z(cbSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
381 PMMHEAPHDR pHdr = (PMMHEAPHDR)(fZero ? RTMemAllocZ(cbSize) : RTMemAlloc(cbSize));
382 if (!pHdr)
383 {
384 AssertMsgFailed(("Failed to allocate heap block %d, enmTag=%x(%.4s).\n", cbSize, enmTag, &enmTag));
385#ifdef MMR3HEAP_WITH_STATISTICS
386 RTCritSectEnter(&pHeap->Lock);
387 pStat->cFailures++;
388 pHeap->Stat.cFailures++;
389 RTCritSectLeave(&pHeap->Lock);
390#endif
391 return NULL;
392 }
393 Assert(!((uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1)));
394
395 RTCritSectEnter(&pHeap->Lock);
396
397 /*
398 * Init and link in the header.
399 */
400 pHdr->pNext = NULL;
401 pHdr->pPrev = pHeap->pTail;
402 if (pHdr->pPrev)
403 pHdr->pPrev->pNext = pHdr;
404 else
405 pHeap->pHead = pHdr;
406 pHeap->pTail = pHdr;
407#ifdef MMR3HEAP_WITH_STATISTICS
408 pHdr->pStat = pStat;
409#else
410 pHdr->pStat = &pHeap->Stat;
411#endif
412 pHdr->cbSize = cbSize;
413
414 /*
415 * Update statistics
416 */
417#ifdef MMR3HEAP_WITH_STATISTICS
418 pStat->cbAllocated += cbSize;
419 pStat->cbCurAllocated += cbSize;
420 pHeap->Stat.cbAllocated += cbSize;
421 pHeap->Stat.cbCurAllocated += cbSize;
422#endif
423
424 RTCritSectLeave(&pHeap->Lock);
425
426 return pHdr + 1;
427}
428
429
430/**
431 * Reallocate memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
432 *
433 * @returns Pointer to reallocated memory.
434 * @param pv Pointer to the memory block to reallocate.
435 * Must not be NULL!
436 * @param cbNewSize New block size.
437 */
438MMR3DECL(void *) MMR3HeapRealloc(void *pv, size_t cbNewSize)
439{
440 AssertMsg(pv, ("Invalid pointer pv=%p\n", pv));
441 if (!pv)
442 return NULL;
443
444 /*
445 * If newsize is zero then this is a free.
446 */
447 if (!cbNewSize)
448 {
449 MMR3HeapFree(pv);
450 return NULL;
451 }
452
453 /*
454 * Validate header.
455 */
456 PMMHEAPHDR pHdr = (PMMHEAPHDR)pv - 1;
457 if ( pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
458 || (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
459 {
460 AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
461 return NULL;
462 }
463 Assert(pHdr->pStat != NULL);
464 Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
465 Assert(!((uintptr_t)pHdr->pPrev & (RTMEM_ALIGNMENT - 1)));
466
467 PMMHEAP pHeap = pHdr->pStat->pHeap;
468
469#ifdef MMR3HEAP_WITH_STATISTICS
470 RTCritSectEnter(&pHeap->Lock);
471 pHdr->pStat->cReallocations++;
472 pHeap->Stat.cReallocations++;
473 RTCritSectLeave(&pHeap->Lock);
474#endif
475
476 /*
477 * Rellocate the block.
478 */
479 cbNewSize = RT_ALIGN_Z(cbNewSize, MMR3HEAP_SIZE_ALIGNMENT) + sizeof(MMHEAPHDR);
480 PMMHEAPHDR pHdrNew = (PMMHEAPHDR)RTMemRealloc(pHdr, cbNewSize);
481 if (!pHdrNew)
482 {
483#ifdef MMR3HEAP_WITH_STATISTICS
484 RTCritSectEnter(&pHeap->Lock);
485 pHdr->pStat->cFailures++;
486 pHeap->Stat.cFailures++;
487 RTCritSectLeave(&pHeap->Lock);
488#endif
489 return NULL;
490 }
491
492 /*
493 * Update pointers.
494 */
495 if (pHdrNew != pHdr)
496 {
497 RTCritSectEnter(&pHeap->Lock);
498 if (pHdrNew->pPrev)
499 pHdrNew->pPrev->pNext = pHdrNew;
500 else
501 pHeap->pHead = pHdrNew;
502
503 if (pHdrNew->pNext)
504 pHdrNew->pNext->pPrev = pHdrNew;
505 else
506 pHeap->pTail = pHdrNew;
507 RTCritSectLeave(&pHeap->Lock);
508 }
509
510 /*
511 * Update statistics.
512 */
513#ifdef MMR3HEAP_WITH_STATISTICS
514 RTCritSectEnter(&pHeap->Lock);
515 pHdrNew->pStat->cbAllocated += cbNewSize - pHdrNew->cbSize;
516 pHeap->Stat.cbAllocated += cbNewSize - pHdrNew->cbSize;
517 RTCritSectLeave(&pHeap->Lock);
518#endif
519
520 pHdrNew->cbSize = cbNewSize;
521
522 return pHdrNew + 1;
523}
524
525
526/**
527 * Duplicates the specified string.
528 *
529 * @returns Pointer to the duplicate.
530 * @returns NULL on failure or when input NULL.
531 * @param pUVM Pointer to the user mode VM structure.
532 * @param enmTag Statistics tag. Statistics are collected on a per tag
533 * basis in addition to a global one. Thus we can easily
534 * identify how memory is used by the VM.
535 * @param psz The string to duplicate. NULL is allowed.
536 */
537MMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz)
538{
539 if (!psz)
540 return NULL;
541 AssertPtr(psz);
542
543 size_t cch = strlen(psz) + 1;
544 char *pszDup = (char *)MMR3HeapAllocU(pUVM, enmTag, cch);
545 if (pszDup)
546 memcpy(pszDup, psz, cch);
547 return pszDup;
548}
549
550
551/**
552 * Duplicates the specified string.
553 *
554 * @returns Pointer to the duplicate.
555 * @returns NULL on failure or when input NULL.
556 * @param pVM The VM handle.
557 * @param enmTag Statistics tag. Statistics are collected on a per tag
558 * basis in addition to a global one. Thus we can easily
559 * identify how memory is used by the VM.
560 * @param psz The string to duplicate. NULL is allowed.
561 */
562MMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz)
563{
564 return MMR3HeapStrDupU(pVM->pUVM, enmTag, psz);
565}
566
567
568/**
569 * Releases memory allocated with MMR3HeapAlloc() or MMR3HeapRealloc().
570 *
571 * @param pv Pointer to the memory block to free.
572 */
573MMR3DECL(void) MMR3HeapFree(void *pv)
574{
575 /* Ignore NULL pointers. */
576 if (!pv)
577 return;
578
579 /*
580 * Validate header.
581 */
582 PMMHEAPHDR pHdr = (PMMHEAPHDR)pv - 1;
583 if ( pHdr->cbSize & (MMR3HEAP_SIZE_ALIGNMENT - 1)
584 || (uintptr_t)pHdr & (RTMEM_ALIGNMENT - 1))
585 {
586 AssertMsgFailed(("Invalid heap header! pv=%p, size=%#x\n", pv, pHdr->cbSize));
587 return;
588 }
589 Assert(pHdr->pStat != NULL);
590 Assert(!((uintptr_t)pHdr->pNext & (RTMEM_ALIGNMENT - 1)));
591 Assert(!((uintptr_t)pHdr->pPrev & (RTMEM_ALIGNMENT - 1)));
592
593 /*
594 * Update statistics
595 */
596 PMMHEAP pHeap = pHdr->pStat->pHeap;
597 RTCritSectEnter(&pHeap->Lock);
598
599#ifdef MMR3HEAP_WITH_STATISTICS
600 pHdr->pStat->cFrees++;
601 pHeap->Stat.cFrees++;
602 pHdr->pStat->cbFreed += pHdr->cbSize;
603 pHeap->Stat.cbFreed += pHdr->cbSize;
604 pHdr->pStat->cbCurAllocated -= pHdr->cbSize;
605 pHeap->Stat.cbCurAllocated -= pHdr->cbSize;
606#endif
607
608 /*
609 * Unlink it.
610 */
611 if (pHdr->pPrev)
612 pHdr->pPrev->pNext = pHdr->pNext;
613 else
614 pHeap->pHead = pHdr->pNext;
615
616 if (pHdr->pNext)
617 pHdr->pNext->pPrev = pHdr->pPrev;
618 else
619 pHeap->pTail = pHdr->pPrev;
620
621 RTCritSectLeave(&pHeap->Lock);
622
623 /*
624 * Free the memory.
625 */
626 RTMemFree(pHdr);
627}
628
629
630/**
631 * Gets the string name of a memory tag.
632 *
633 * @returns name of enmTag.
634 * @param enmTag The tag.
635 */
636const char *mmR3GetTagName(MMTAG enmTag)
637{
638 switch (enmTag)
639 {
640 #define TAG2STR(tag) case MM_TAG_##tag: return #tag
641
642 TAG2STR(CFGM);
643 TAG2STR(CFGM_BYTES);
644 TAG2STR(CFGM_STRING);
645 TAG2STR(CFGM_USER);
646
647 TAG2STR(CSAM);
648 TAG2STR(CSAM_PATCH);
649
650 TAG2STR(DBGF);
651 TAG2STR(DBGF_INFO);
652 TAG2STR(DBGF_LINE);
653 TAG2STR(DBGF_LINE_DUP);
654 TAG2STR(DBGF_STACK);
655 TAG2STR(DBGF_SYMBOL);
656 TAG2STR(DBGF_SYMBOL_DUP);
657 TAG2STR(DBGF_MODULE);
658
659 TAG2STR(EM);
660
661 TAG2STR(IOM);
662 TAG2STR(IOM_STATS);
663
664 TAG2STR(MM);
665 TAG2STR(MM_LOOKUP_GUEST);
666 TAG2STR(MM_LOOKUP_PHYS);
667 TAG2STR(MM_LOOKUP_VIRT);
668 TAG2STR(MM_PAGE);
669
670 TAG2STR(PATM);
671 TAG2STR(PATM_PATCH);
672
673 TAG2STR(PDM);
674 TAG2STR(PDM_DEVICE);
675 TAG2STR(PDM_DEVICE_USER);
676 TAG2STR(PDM_DRIVER);
677 TAG2STR(PDM_DRIVER_USER);
678 TAG2STR(PDM_USB);
679 TAG2STR(PDM_USB_USER);
680 TAG2STR(PDM_LUN);
681 TAG2STR(PDM_QUEUE);
682 TAG2STR(PDM_THREAD);
683 TAG2STR(PDM_ASYNC_COMPLETION);
684
685 TAG2STR(PGM);
686 TAG2STR(PGM_CHUNK_MAPPING);
687 TAG2STR(PGM_HANDLERS);
688 TAG2STR(PGM_PHYS);
689 TAG2STR(PGM_POOL);
690
691 TAG2STR(REM);
692
693 TAG2STR(SELM);
694
695 TAG2STR(SSM);
696
697 TAG2STR(STAM);
698
699 TAG2STR(TM);
700
701 TAG2STR(TRPM);
702
703 TAG2STR(VM);
704 TAG2STR(VM_REQ);
705
706 TAG2STR(VMM);
707
708 TAG2STR(HWACCM);
709
710 #undef TAG2STR
711
712 default:
713 {
714 AssertMsgFailed(("Unknown tag %d! forgot to add it to the switch?\n", enmTag));
715 static char sz[48];
716 RTStrPrintf(sz, sizeof(sz), "%d", enmTag);
717 return sz;
718 }
719 }
720}
721
Note: See TracBrowser for help on using the repository browser.

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