VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibPhysHeap.cpp@ 83142

Last change on this file since 83142 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/* $Id: VBoxGuestR0LibPhysHeap.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * VBoxGuestLibR0 - Physical memory heap.
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31
32/*********************************************************************************************************************************
33* Header Files *
34*********************************************************************************************************************************/
35#include "VBoxGuestR0LibInternal.h"
36
37#include <iprt/assert.h>
38#include <iprt/semaphore.h>
39#include <iprt/alloc.h>
40
41/* Physical memory heap consists of double linked list
42 * of chunks. Memory blocks are allocated inside these chunks
43 * and are members of Allocated and Free double linked lists.
44 *
45 * When allocating a block, we search in Free linked
46 * list for a suitable free block. If there is no such block,
47 * a new chunk is allocated and the new block is taken from
48 * the new chunk as the only chunk-sized free block.
49 * Allocated block is excluded from the Free list and goes to
50 * Alloc list.
51 *
52 * When freeing block, we check the pointer and then
53 * exclude block from Alloc list and move it to free list.
54 *
55 * For each chunk we maintain the allocated blocks counter.
56 * if 2 (or more) entire chunks are free they are immediately
57 * deallocated, so we always have at most 1 free chunk.
58 *
59 * When freeing blocks, two subsequent free blocks are always
60 * merged together. Current implementation merges blocks only
61 * when there is a block after the just freed one.
62 *
63 */
64
65#define VBGL_PH_ASSERT Assert
66#define VBGL_PH_ASSERTMsg AssertMsg
67
68// #define DUMPHEAP
69
70#ifdef DUMPHEAP
71# define VBGL_PH_dprintf(a) RTAssertMsg2Weak a
72#else
73# define VBGL_PH_dprintf(a)
74#endif
75
76/* Heap block signature */
77#define VBGL_PH_BLOCKSIGNATURE (0xADDBBBBB)
78
79
80/* Heap chunk signature */
81#define VBGL_PH_CHUNKSIGNATURE (0xADDCCCCC)
82/* Heap chunk allocation unit */
83#define VBGL_PH_CHUNKSIZE (0x10000)
84
85/* Heap block bit flags */
86#define VBGL_PH_BF_ALLOCATED (0x1)
87
88struct _VBGLPHYSHEAPBLOCK
89{
90 uint32_t u32Signature;
91
92 /* Size of user data in the block. Does not include the block header. */
93 uint32_t cbDataSize;
94
95 uint32_t fu32Flags;
96
97 struct _VBGLPHYSHEAPBLOCK *pNext;
98 struct _VBGLPHYSHEAPBLOCK *pPrev;
99
100 struct _VBGLPHYSHEAPCHUNK *pChunk;
101};
102
103struct _VBGLPHYSHEAPCHUNK
104{
105 uint32_t u32Signature;
106
107 /* Size of the chunk. Includes the chunk header. */
108 uint32_t cbSize;
109
110 /* Physical address of the chunk */
111 uint32_t physAddr;
112
113 /* Number of allocated blocks in the chunk */
114 int32_t cAllocatedBlocks;
115
116 struct _VBGLPHYSHEAPCHUNK *pNext;
117 struct _VBGLPHYSHEAPCHUNK *pPrev;
118};
119
120
121#ifndef DUMPHEAP
122#define dumpheap(a)
123#else
124void dumpheap (char *point)
125{
126 VBGL_PH_dprintf(("VBGL_PH dump at '%s'\n", point));
127
128 VBGL_PH_dprintf(("Chunks:\n"));
129
130 VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
131
132 while (pChunk)
133 {
134 VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, allocated = %8d, phys = %08X\n",
135 pChunk, pChunk->pNext, pChunk->pPrev, pChunk->u32Signature, pChunk->cbSize, pChunk->cAllocatedBlocks, pChunk->physAddr));
136
137 pChunk = pChunk->pNext;
138 }
139
140 VBGL_PH_dprintf(("Allocated blocks:\n"));
141
142 VBGLPHYSHEAPBLOCK *pBlock = g_vbgldata.pAllocBlocksHead;
143
144 while (pBlock)
145 {
146 VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
147 pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
148
149 pBlock = pBlock->pNext;
150 }
151
152 VBGL_PH_dprintf(("Free blocks:\n"));
153
154 pBlock = g_vbgldata.pFreeBlocksHead;
155
156 while (pBlock)
157 {
158 VBGL_PH_dprintf(("%p: pNext = %p, pPrev = %p, sign = %08X, size = %8d, flags = %08X, pChunk = %p\n",
159 pBlock, pBlock->pNext, pBlock->pPrev, pBlock->u32Signature, pBlock->cbDataSize, pBlock->fu32Flags, pBlock->pChunk));
160
161 pBlock = pBlock->pNext;
162 }
163
164 VBGL_PH_dprintf(("VBGL_PH dump at '%s' done\n", point));
165}
166#endif
167
168
169DECLINLINE(void *) vbglPhysHeapBlock2Data (VBGLPHYSHEAPBLOCK *pBlock)
170{
171 return (void *)(pBlock? (char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK): NULL);
172}
173
174DECLINLINE(VBGLPHYSHEAPBLOCK *) vbglPhysHeapData2Block (void *p)
175{
176 VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)(p? (char *)p - sizeof (VBGLPHYSHEAPBLOCK): NULL);
177
178 VBGL_PH_ASSERTMsg(pBlock == NULL || pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
179 ("pBlock->u32Signature = %08X\n", pBlock->u32Signature));
180
181 return pBlock;
182}
183
184DECLINLINE(int) vbglPhysHeapEnter (void)
185{
186 int rc = RTSemFastMutexRequest(g_vbgldata.mutexHeap);
187
188 VBGL_PH_ASSERTMsg(RT_SUCCESS(rc),
189 ("Failed to request heap mutex, rc = %Rrc\n", rc));
190
191 return rc;
192}
193
194DECLINLINE(void) vbglPhysHeapLeave (void)
195{
196 RTSemFastMutexRelease(g_vbgldata.mutexHeap);
197}
198
199
200static void vbglPhysHeapInitBlock (VBGLPHYSHEAPBLOCK *pBlock, VBGLPHYSHEAPCHUNK *pChunk, uint32_t cbDataSize)
201{
202 VBGL_PH_ASSERT(pBlock != NULL);
203 VBGL_PH_ASSERT(pChunk != NULL);
204
205 pBlock->u32Signature = VBGL_PH_BLOCKSIGNATURE;
206 pBlock->cbDataSize = cbDataSize;
207 pBlock->fu32Flags = 0;
208 pBlock->pNext = NULL;
209 pBlock->pPrev = NULL;
210 pBlock->pChunk = pChunk;
211}
212
213
214static void vbglPhysHeapInsertBlock (VBGLPHYSHEAPBLOCK *pInsertAfter, VBGLPHYSHEAPBLOCK *pBlock)
215{
216 VBGL_PH_ASSERTMsg(pBlock->pNext == NULL,
217 ("pBlock->pNext = %p\n", pBlock->pNext));
218 VBGL_PH_ASSERTMsg(pBlock->pPrev == NULL,
219 ("pBlock->pPrev = %p\n", pBlock->pPrev));
220
221 if (pInsertAfter)
222 {
223 pBlock->pNext = pInsertAfter->pNext;
224 pBlock->pPrev = pInsertAfter;
225
226 if (pInsertAfter->pNext)
227 {
228 pInsertAfter->pNext->pPrev = pBlock;
229 }
230
231 pInsertAfter->pNext = pBlock;
232 }
233 else
234 {
235 /* inserting to head of list */
236 pBlock->pPrev = NULL;
237
238 if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
239 {
240 pBlock->pNext = g_vbgldata.pAllocBlocksHead;
241
242 if (g_vbgldata.pAllocBlocksHead)
243 {
244 g_vbgldata.pAllocBlocksHead->pPrev = pBlock;
245 }
246
247 g_vbgldata.pAllocBlocksHead = pBlock;
248 }
249 else
250 {
251 pBlock->pNext = g_vbgldata.pFreeBlocksHead;
252
253 if (g_vbgldata.pFreeBlocksHead)
254 {
255 g_vbgldata.pFreeBlocksHead->pPrev = pBlock;
256 }
257
258 g_vbgldata.pFreeBlocksHead = pBlock;
259 }
260 }
261}
262
263static void vbglPhysHeapExcludeBlock (VBGLPHYSHEAPBLOCK *pBlock)
264{
265 if (pBlock->pNext)
266 {
267 pBlock->pNext->pPrev = pBlock->pPrev;
268 }
269 else
270 {
271 /* this is tail of list but we do not maintain tails of block lists.
272 * so do nothing.
273 */
274 ;
275 }
276
277 if (pBlock->pPrev)
278 {
279 pBlock->pPrev->pNext = pBlock->pNext;
280 }
281 else
282 {
283 /* this is head of list but we do not maintain tails of block lists. */
284 if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
285 {
286 g_vbgldata.pAllocBlocksHead = pBlock->pNext;
287 }
288 else
289 {
290 g_vbgldata.pFreeBlocksHead = pBlock->pNext;
291 }
292 }
293
294 pBlock->pNext = NULL;
295 pBlock->pPrev = NULL;
296}
297
298static VBGLPHYSHEAPBLOCK *vbglPhysHeapChunkAlloc (uint32_t cbSize)
299{
300 RTCCPHYS physAddr;
301 VBGLPHYSHEAPCHUNK *pChunk;
302 VBGLPHYSHEAPBLOCK *pBlock;
303 VBGL_PH_dprintf(("Allocating new chunk of size %d\n", cbSize));
304
305 /* Compute chunk size to allocate */
306 if (cbSize < VBGL_PH_CHUNKSIZE)
307 {
308 /* Includes case of block size 0 during initialization */
309 cbSize = VBGL_PH_CHUNKSIZE;
310 }
311 else
312 {
313 /* Round up to next chunk size, which must be power of 2 */
314 cbSize = (cbSize + (VBGL_PH_CHUNKSIZE - 1)) & ~(VBGL_PH_CHUNKSIZE - 1);
315 }
316
317 physAddr = 0;
318 /* This function allocates physical contiguous memory (below 4GB) according to the IPRT docs.
319 * Address < 4G is required for the port IO.
320 */
321 pChunk = (VBGLPHYSHEAPCHUNK *)RTMemContAlloc (&physAddr, cbSize);
322
323 if (!pChunk)
324 {
325 LogRel(("vbglPhysHeapChunkAlloc: failed to alloc %u contiguous bytes.\n", cbSize));
326 return NULL;
327 }
328
329 AssertRelease(physAddr < _4G && physAddr + cbSize <= _4G);
330
331 pChunk->u32Signature = VBGL_PH_CHUNKSIGNATURE;
332 pChunk->cbSize = cbSize;
333 pChunk->physAddr = (uint32_t)physAddr;
334 pChunk->cAllocatedBlocks = 0;
335 pChunk->pNext = g_vbgldata.pChunkHead;
336 pChunk->pPrev = NULL;
337
338 /* Initialize the free block, which now occupies entire chunk. */
339 pBlock = (VBGLPHYSHEAPBLOCK *)((char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK));
340
341 vbglPhysHeapInitBlock (pBlock, pChunk, cbSize - sizeof (VBGLPHYSHEAPCHUNK) - sizeof (VBGLPHYSHEAPBLOCK));
342
343 vbglPhysHeapInsertBlock (NULL, pBlock);
344
345 g_vbgldata.pChunkHead = pChunk;
346
347 VBGL_PH_dprintf(("Allocated chunk %p, block = %p size=%x\n", pChunk, pBlock, cbSize));
348
349 return pBlock;
350}
351
352
353static void vbglPhysHeapChunkDelete (VBGLPHYSHEAPCHUNK *pChunk)
354{
355 char *p;
356 VBGL_PH_ASSERT(pChunk != NULL);
357 VBGL_PH_ASSERTMsg(pChunk->u32Signature == VBGL_PH_CHUNKSIGNATURE,
358 ("pChunk->u32Signature = %08X\n", pChunk->u32Signature));
359
360 VBGL_PH_dprintf(("Deleting chunk %p size %x\n", pChunk, pChunk->cbSize));
361
362 /* first scan the chunk and exclude all blocks from lists */
363
364 p = (char *)pChunk + sizeof (VBGLPHYSHEAPCHUNK);
365
366 while (p < (char *)pChunk + pChunk->cbSize)
367 {
368 VBGLPHYSHEAPBLOCK *pBlock = (VBGLPHYSHEAPBLOCK *)p;
369
370 p += pBlock->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
371
372 vbglPhysHeapExcludeBlock (pBlock);
373 }
374
375 VBGL_PH_ASSERTMsg(p == (char *)pChunk + pChunk->cbSize,
376 ("p = %p, (char *)pChunk + pChunk->cbSize = %p, pChunk->cbSize = %08X\n",
377 p, (char *)pChunk + pChunk->cbSize, pChunk->cbSize));
378
379 /* Exclude chunk from the chunk list */
380 if (pChunk->pNext)
381 {
382 pChunk->pNext->pPrev = pChunk->pPrev;
383 }
384 else
385 {
386 /* we do not maintain tail */
387 ;
388 }
389
390 if (pChunk->pPrev)
391 {
392 pChunk->pPrev->pNext = pChunk->pNext;
393 }
394 else
395 {
396 /* the chunk was head */
397 g_vbgldata.pChunkHead = pChunk->pNext;
398 }
399
400 RTMemContFree (pChunk, pChunk->cbSize);
401}
402
403
404DECLR0VBGL(void *) VbglR0PhysHeapAlloc (uint32_t cbSize)
405{
406 VBGLPHYSHEAPBLOCK *pBlock, *pIter;
407 int rc = vbglPhysHeapEnter ();
408
409 if (RT_FAILURE(rc))
410 return NULL;
411
412 dumpheap ("pre alloc");
413
414 /*
415 * Search the free list. We do this in linear fashion as we don't expect
416 * there to be many blocks in the heap.
417 */
418
419 pBlock = NULL;
420 if (cbSize <= PAGE_SIZE / 4 * 3)
421 {
422 /* Smaller than 3/4 page: Prefer a free block that can keep the request within a single page,
423 so HGCM processing in VMMDev can use page locks instead of several reads and writes. */
424
425 VBGLPHYSHEAPBLOCK *pFallback = NULL;
426 for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
427 if (pIter->cbDataSize >= cbSize)
428 {
429 if (pIter->cbDataSize == cbSize)
430 {
431 if (PAGE_SIZE - ((uintptr_t)vbglPhysHeapBlock2Data(pIter) & PAGE_OFFSET_MASK) >= cbSize)
432 {
433 pBlock = pIter;
434 break;
435 }
436 pFallback = pIter;
437 }
438 else
439 {
440 if (!pFallback || pIter->cbDataSize < pFallback->cbDataSize)
441 pFallback = pIter;
442 if (PAGE_SIZE - ((uintptr_t)vbglPhysHeapBlock2Data(pIter) & PAGE_OFFSET_MASK) >= cbSize)
443 if (!pBlock || pIter->cbDataSize < pBlock->cbDataSize)
444 pBlock = pIter;
445 }
446 }
447
448 if (!pBlock)
449 pBlock = pFallback;
450 }
451 else
452 {
453 /* Large than 3/4 page: Find smallest free list match. */
454
455 for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
456 if (pIter->cbDataSize >= cbSize)
457 {
458 if (pIter->cbDataSize == cbSize)
459 {
460 /* Exact match - we're done! */
461 pBlock = pIter;
462 break;
463 }
464
465 /* Looking for a free block with nearest size. */
466 if (!pBlock || pIter->cbDataSize < pBlock->cbDataSize)
467 pBlock = pIter;
468 }
469 }
470
471 if (!pBlock)
472 {
473 /* No free blocks, allocate a new chunk,
474 * the only free block of the chunk will
475 * be returned.
476 */
477 pBlock = vbglPhysHeapChunkAlloc (cbSize);
478 }
479
480 if (pBlock)
481 {
482 VBGL_PH_ASSERTMsg(pBlock->u32Signature == VBGL_PH_BLOCKSIGNATURE,
483 ("pBlock = %p, pBlock->u32Signature = %08X\n", pBlock, pBlock->u32Signature));
484 VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0,
485 ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
486
487 /* We have a free block, either found or allocated. */
488
489 if (pBlock->cbDataSize > 2*(cbSize + sizeof (VBGLPHYSHEAPBLOCK)))
490 {
491 /* Data will occupy less than a half of the block,
492 * split off the tail end into a new free list entry.
493 */
494 pIter = (VBGLPHYSHEAPBLOCK *)((char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK) + cbSize);
495
496 /* Init the new 'pIter' block, initialized blocks are always marked as free. */
497 vbglPhysHeapInitBlock (pIter, pBlock->pChunk, pBlock->cbDataSize - cbSize - sizeof (VBGLPHYSHEAPBLOCK));
498
499 pBlock->cbDataSize = cbSize;
500
501 /* Insert the new 'pIter' block after the 'pBlock' in the free list */
502 vbglPhysHeapInsertBlock (pBlock, pIter);
503 }
504
505 /* Exclude pBlock from free list */
506 vbglPhysHeapExcludeBlock (pBlock);
507
508 /* Mark as allocated */
509 pBlock->fu32Flags |= VBGL_PH_BF_ALLOCATED;
510
511 /* Insert to allocated list */
512 vbglPhysHeapInsertBlock (NULL, pBlock);
513
514 /* Adjust the chunk allocated blocks counter */
515 pBlock->pChunk->cAllocatedBlocks++;
516 }
517
518 dumpheap ("post alloc");
519
520 vbglPhysHeapLeave ();
521 VBGL_PH_dprintf(("VbglR0PhysHeapAlloc %x size %x\n", vbglPhysHeapBlock2Data (pBlock), pBlock->cbDataSize));
522
523 return vbglPhysHeapBlock2Data (pBlock);
524}
525
526DECLR0VBGL(uint32_t) VbglR0PhysHeapGetPhysAddr (void *p)
527{
528 uint32_t physAddr = 0;
529 VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapData2Block (p);
530
531 if (pBlock)
532 {
533 VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
534 ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
535
536 if (pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED)
537 physAddr = pBlock->pChunk->physAddr + (uint32_t)((uintptr_t)p - (uintptr_t)pBlock->pChunk);
538 }
539
540 return physAddr;
541}
542
543DECLR0VBGL(void) VbglR0PhysHeapFree(void *p)
544{
545 VBGLPHYSHEAPBLOCK *pBlock;
546 VBGLPHYSHEAPBLOCK *pNeighbour;
547
548 int rc = vbglPhysHeapEnter ();
549 if (RT_FAILURE(rc))
550 return;
551
552 dumpheap ("pre free");
553
554 pBlock = vbglPhysHeapData2Block (p);
555
556 if (!pBlock)
557 {
558 vbglPhysHeapLeave ();
559 return;
560 }
561
562 VBGL_PH_ASSERTMsg((pBlock->fu32Flags & VBGL_PH_BF_ALLOCATED) != 0,
563 ("pBlock = %p, pBlock->fu32Flags = %08X\n", pBlock, pBlock->fu32Flags));
564
565 /* Exclude from allocated list */
566 vbglPhysHeapExcludeBlock (pBlock);
567
568 dumpheap ("post exclude");
569
570 VBGL_PH_dprintf(("VbglR0PhysHeapFree %x size %x\n", p, pBlock->cbDataSize));
571
572 /* Mark as free */
573 pBlock->fu32Flags &= ~VBGL_PH_BF_ALLOCATED;
574
575 /* Insert to free list */
576 vbglPhysHeapInsertBlock (NULL, pBlock);
577
578 dumpheap ("post insert");
579
580 /* Adjust the chunk allocated blocks counter */
581 pBlock->pChunk->cAllocatedBlocks--;
582
583 VBGL_PH_ASSERT(pBlock->pChunk->cAllocatedBlocks >= 0);
584
585 /* Check if we can merge 2 free blocks. To simplify heap maintenance,
586 * we will look at block after the just freed one.
587 * This will not prevent us from detecting free memory chunks.
588 * Also in most cases blocks are deallocated in reverse allocation order
589 * and in that case the merging will work.
590 */
591
592 pNeighbour = (VBGLPHYSHEAPBLOCK *)((char *)p + pBlock->cbDataSize);
593
594 if ((char *)pNeighbour < (char *)pBlock->pChunk + pBlock->pChunk->cbSize
595 && (pNeighbour->fu32Flags & VBGL_PH_BF_ALLOCATED) == 0)
596 {
597 /* The next block is free as well. */
598
599 /* Adjust size of current memory block */
600 pBlock->cbDataSize += pNeighbour->cbDataSize + sizeof (VBGLPHYSHEAPBLOCK);
601
602 /* Exclude the next neighbour */
603 vbglPhysHeapExcludeBlock (pNeighbour);
604 }
605
606 dumpheap ("post merge");
607
608 /* now check if there are 2 or more free chunks */
609 if (pBlock->pChunk->cAllocatedBlocks == 0)
610 {
611 VBGLPHYSHEAPCHUNK *pChunk = g_vbgldata.pChunkHead;
612
613 uint32_t u32FreeChunks = 0;
614
615 while (pChunk)
616 {
617 if (pChunk->cAllocatedBlocks == 0)
618 {
619 u32FreeChunks++;
620 }
621
622 pChunk = pChunk->pNext;
623 }
624
625 if (u32FreeChunks > 1)
626 {
627 /* Delete current chunk, it will also exclude all free blocks
628 * remaining in the chunk from the free list, so the pBlock
629 * will also be invalid after this.
630 */
631 vbglPhysHeapChunkDelete (pBlock->pChunk);
632 }
633 }
634
635 dumpheap ("post free");
636
637 vbglPhysHeapLeave ();
638}
639
640DECLR0VBGL(int) VbglR0PhysHeapInit (void)
641{
642 int rc = VINF_SUCCESS;
643
644 /* Allocate the first chunk of the heap. */
645 VBGLPHYSHEAPBLOCK *pBlock = vbglPhysHeapChunkAlloc (0);
646
647 if (!pBlock)
648 rc = VERR_NO_MEMORY;
649
650 RTSemFastMutexCreate(&g_vbgldata.mutexHeap);
651
652 return rc;
653}
654
655DECLR0VBGL(void) VbglR0PhysHeapTerminate (void)
656{
657 while (g_vbgldata.pChunkHead)
658 {
659 vbglPhysHeapChunkDelete (g_vbgldata.pChunkHead);
660 }
661
662 RTSemFastMutexDestroy(g_vbgldata.mutexHeap);
663}
664
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