- Timestamp:
- Sep 18, 2023 2:18:29 PM (20 months ago)
- svn:sync-xref-src-repo-rev:
- 159123
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp ¶
r101148 r101150 47 47 #include <iprt/critsect.h> 48 48 #include <iprt/errcore.h> 49 #include <iprt/list.h> 49 50 #include <iprt/once.h> 50 51 #include <iprt/param.h> 51 52 #include <iprt/string.h> 52 #include "internal/mem.h" 53 #include "../alloc-ef.h" 53 /*#include "internal/mem.h"*/ 54 54 55 55 #include <stdlib.h> … … 65 65 *********************************************************************************************************************************/ 66 66 /** Threshold at which to we switch to simply calling mmap. */ 67 #define RTMEMPAGEPOSIX_MMAP_THRESHOLD _1 28K67 #define RTMEMPAGEPOSIX_MMAP_THRESHOLD _1M 68 68 /** The size of a heap block (power of two) - in bytes. */ 69 69 #define RTMEMPAGEPOSIX_BLOCK_SIZE _2M 70 70 71 AssertCompile(RTMEMPAGEPOSIX_BLOCK_SIZE == (RTMEMPAGEPOSIX_BLOCK_SIZE / PAGE_SIZE) * PAGE_SIZE); 71 72 /** The number of pages per heap block. */ … … 102 103 /** Allocation hint no 2 (last alloc). */ 103 104 PRTHEAPPAGEBLOCK pHint2; 105 /** The allocation chunks for the RTHEAPPAGEBLOCK allocator 106 * (RTHEAPPAGEBLOCKALLOCCHUNK). */ 107 RTLISTANCHOR BlockAllocatorChunks; 104 108 /** Critical section protecting the heap. */ 105 109 RTCRITSECT CritSect; … … 138 142 139 143 /** 144 * Allocation chunk of RTHEAPPAGEBLOCKALLOCCHUNK structures. 145 * 146 * This is backed by an 64KB allocation and non-present blocks will be marked as 147 * allocated in bmAlloc. 148 */ 149 typedef struct RTHEAPPAGEBLOCKALLOCCHUNK 150 { 151 /** List entry. */ 152 RTLISTNODE ListEntry; 153 /** Number of free RTHEAPPAGEBLOCK structures here. */ 154 uint32_t cFree; 155 /** Number of blocks in aBlocks. */ 156 uint32_t cBlocks; 157 /** Allocation bitmap. */ 158 uint32_t bmAlloc[ARCH_BITS == 32 ? 28 : 26]; 159 /** Block array. */ 160 RT_FLEXIBLE_ARRAY_EXTENSION 161 RTHEAPPAGEBLOCK aBlocks[RT_FLEXIBLE_ARRAY]; 162 } RTHEAPPAGEBLOCKALLOCCHUNK; 163 AssertCompileMemberAlignment(RTHEAPPAGEBLOCKALLOCCHUNK, bmAlloc, 8); 164 AssertCompileMemberAlignment(RTHEAPPAGEBLOCKALLOCCHUNK, aBlocks, 64); 165 /** Pointer to an allocation chunk of RTHEAPPAGEBLOCKALLOCCHUNK structures. */ 166 typedef RTHEAPPAGEBLOCKALLOCCHUNK *PRTHEAPPAGEBLOCKALLOCCHUNK; 167 168 /** Max number of blocks one RTHEAPPAGEBLOCKALLOCCHUNK can track (896/832). */ 169 #define RTHEAPPAGEBLOCKALLOCCHUNK_MAX_BLOCKS ((ARCH_BITS == 32 ? 28 : 26) * 32) 170 /** The chunk size for the block allocator. */ 171 #define RTHEAPPAGEBLOCKALLOCCHUNK_ALLOC_SIZE _64K 172 173 174 /** 140 175 * Argument package for rtHeapPageAllocCallback. 141 176 */ … … 285 320 pHeap->BlockTree = NULL; 286 321 pHeap->fExec = fExec; 322 RTListInit(&pHeap->BlockAllocatorChunks); 287 323 pHeap->u32Magic = RTHEAPPAGE_MAGIC; 288 324 } … … 302 338 pHeap->u32Magic = ~RTHEAPPAGE_MAGIC; 303 339 return VINF_SUCCESS; 340 } 341 342 343 /** 344 * Allocates a RTHEAPPAGEBLOCK. 345 * 346 * @returns Pointer to RTHEAPPAGEBLOCK on success, NULL on failure. 347 * @param pHeap The heap this is for. 348 */ 349 static PRTHEAPPAGEBLOCK rtHeapPageIntBlockAllocatorAlloc(PRTHEAPPAGE pHeap) 350 { 351 /* 352 * Locate a chunk with space and grab a block from it. 353 */ 354 PRTHEAPPAGEBLOCKALLOCCHUNK pChunk; 355 RTListForEach(&pHeap->BlockAllocatorChunks, pChunk, RTHEAPPAGEBLOCKALLOCCHUNK, ListEntry) 356 { 357 if (pChunk->cFree > 0) 358 { 359 int idxBlock = ASMBitFirstClear(&pChunk->bmAlloc[0], RT_MIN(RTHEAPPAGEBLOCKALLOCCHUNK_MAX_BLOCKS, pChunk->cBlocks)); 360 if (idxBlock >= 0) 361 { 362 ASMBitSet(&pChunk->bmAlloc[0], idxBlock); 363 pChunk->cFree -= 1; 364 return &pChunk->aBlocks[idxBlock]; 365 } 366 AssertFailed(); 367 } 368 } 369 370 /* 371 * Allocate a new chunk and return the first block in it. 372 */ 373 int rc = rtMemPageNativeAlloc(RTHEAPPAGEBLOCKALLOCCHUNK_ALLOC_SIZE, 0, (void **)&pChunk); 374 AssertRCReturn(rc, NULL); 375 pChunk->cBlocks = (RTHEAPPAGEBLOCKALLOCCHUNK_ALLOC_SIZE - RT_UOFFSETOF(RTHEAPPAGEBLOCKALLOCCHUNK, aBlocks)) 376 / sizeof(pChunk->aBlocks[0]); 377 AssertStmt(pChunk->cBlocks < RTHEAPPAGEBLOCKALLOCCHUNK_MAX_BLOCKS, pChunk->cBlocks = RTHEAPPAGEBLOCKALLOCCHUNK_MAX_BLOCKS); 378 pChunk->cFree = pChunk->cBlocks; 379 380 RT_ZERO(pChunk->bmAlloc); 381 ASMBitSetRange(pChunk->bmAlloc, pChunk->cBlocks, RTHEAPPAGEBLOCKALLOCCHUNK_MAX_BLOCKS); 382 RTListPrepend(&pHeap->BlockAllocatorChunks, &pChunk->ListEntry); 383 384 /* 385 * Allocate the first one. 386 */ 387 ASMBitSet(pChunk->bmAlloc, 0); 388 pChunk->cFree -= 1; 389 390 return &pChunk->aBlocks[0]; 391 } 392 393 394 /** 395 * Frees a RTHEAPPAGEBLOCK. 396 * 397 * @param pHeap The heap this is for. 398 * @param pBlock The block to free. 399 */ 400 static void rtHeapPageIntBlockAllocatorFree(PRTHEAPPAGE pHeap, PRTHEAPPAGEBLOCK pBlock) 401 { 402 /* 403 * Locate the chunk the block belongs to and mark it as freed. 404 */ 405 PRTHEAPPAGEBLOCKALLOCCHUNK pChunk; 406 RTListForEach(&pHeap->BlockAllocatorChunks, pChunk, RTHEAPPAGEBLOCKALLOCCHUNK, ListEntry) 407 { 408 if ((uintptr_t)pBlock - (uintptr_t)pChunk < RTHEAPPAGEBLOCKALLOCCHUNK_ALLOC_SIZE) 409 { 410 uintptr_t const idxBlock = (uintptr_t)(pBlock - &pChunk->aBlocks[0]); 411 if (ASMBitTestAndClear(&pChunk->bmAlloc[0], idxBlock)) 412 pChunk->cFree++; 413 else 414 AssertMsgFailed(("pBlock=%p idxBlock=%#zx\n", pBlock, idxBlock)); 415 return; 416 } 417 } 418 AssertFailed(); 304 419 } 305 420 … … 418 533 /* next */ 419 534 iPage = ASMBitNextSet(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT, iPage); 420 if (iPage < 0 || iPage >= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT - 1)535 if (iPage < 0 || (unsigned)iPage >= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT - 1) 421 536 break; 422 537 iPage = ASMBitNextClear(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT, iPage); … … 499 614 * Didn't find anything, so expand the heap with a new block. 500 615 */ 616 PRTHEAPPAGEBLOCK const pBlock = rtHeapPageIntBlockAllocatorAlloc(pHeap); 617 AssertReturn(pBlock, VERR_NO_MEMORY); 618 501 619 RTCritSectLeave(&pHeap->CritSect); 502 620 503 621 void *pvPages = NULL; 504 622 rc = rtMemPageNativeAlloc(RTMEMPAGEPOSIX_BLOCK_SIZE, pHeap->fExec ? RTMEMPAGEALLOC_F_EXECUTABLE : 0, &pvPages); 623 624 RTCritSectEnter(&pHeap->CritSect); 505 625 if (RT_FAILURE(rc)) 506 626 { 507 RTCritSectEnter(&pHeap->CritSect);627 rtHeapPageIntBlockAllocatorFree(pHeap, pBlock); 508 628 return rc; 509 }510 /** @todo Eliminate this rtMemBaseAlloc dependency! */511 PRTHEAPPAGEBLOCK pBlock;512 #ifdef RTALLOC_REPLACE_MALLOC513 if (g_pfnOrgMalloc)514 pBlock = (PRTHEAPPAGEBLOCK)g_pfnOrgMalloc(sizeof(*pBlock));515 else516 #endif517 pBlock = (PRTHEAPPAGEBLOCK)rtMemBaseAlloc(sizeof(*pBlock));518 if (!pBlock)519 {520 rtMemPageNativeFree(pvPages, RTMEMPAGEPOSIX_BLOCK_SIZE);521 RTCritSectEnter(&pHeap->CritSect);522 return VERR_NO_MEMORY;523 629 } 524 630 … … 528 634 pBlock->cFreePages = RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT; 529 635 pBlock->pHeap = pHeap; 530 531 RTCritSectEnter(&pHeap->CritSect);532 636 533 637 bool fRc = RTAvlrPVInsert(&pHeap->BlockTree, &pBlock->Core); Assert(fRc); NOREF(fRc); … … 700 804 pBlock->Core.Key = pBlock->Core.KeyLast = NULL; 701 805 pBlock->cFreePages = 0; 702 #ifdef RTALLOC_REPLACE_MALLOC 703 if (g_pfnOrgFree) 704 g_pfnOrgFree(pBlock); 705 else 706 #endif 707 rtMemBaseFree(pBlock); 806 rtHeapPageIntBlockAllocatorFree(pHeap, pBlock); 708 807 709 808 RTCritSectEnter(&pHeap->CritSect);
Note:
See TracChangeset
for help on using the changeset viewer.