VirtualBox

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

Last change on this file since 8851 was 8797, checked in by vboxsync, 17 years ago

New DBGF interface for digging into the guts of the guest OS kernel.

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