VirtualBox

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

Last change on this file since 4615 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

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