VirtualBox

Changeset 101150 in vbox for trunk


Ignore:
Timestamp:
Sep 18, 2023 2:18:29 PM (20 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159123
Message:

IPRT/mem: Eliminiated the malloc dependency of the rtmempage-exec-mmap-heap-posix.cpp code. Minimally tested. This is in preparation for using this code on Windows. bugref:10370

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp

    r101148 r101150  
    4747#include <iprt/critsect.h>
    4848#include <iprt/errcore.h>
     49#include <iprt/list.h>
    4950#include <iprt/once.h>
    5051#include <iprt/param.h>
    5152#include <iprt/string.h>
    52 #include "internal/mem.h"
    53 #include "../alloc-ef.h"
     53/*#include "internal/mem.h"*/
    5454
    5555#include <stdlib.h>
     
    6565*********************************************************************************************************************************/
    6666/** Threshold at which to we switch to simply calling mmap. */
    67 #define RTMEMPAGEPOSIX_MMAP_THRESHOLD   _128K
     67#define RTMEMPAGEPOSIX_MMAP_THRESHOLD   _1M
    6868/** The size of a heap block (power of two) - in bytes. */
    6969#define RTMEMPAGEPOSIX_BLOCK_SIZE       _2M
     70
    7071AssertCompile(RTMEMPAGEPOSIX_BLOCK_SIZE == (RTMEMPAGEPOSIX_BLOCK_SIZE / PAGE_SIZE) * PAGE_SIZE);
    7172/** The number of pages per heap block. */
     
    102103    /** Allocation hint no 2 (last alloc). */
    103104    PRTHEAPPAGEBLOCK    pHint2;
     105    /** The allocation chunks for the RTHEAPPAGEBLOCK allocator
     106     * (RTHEAPPAGEBLOCKALLOCCHUNK). */
     107    RTLISTANCHOR        BlockAllocatorChunks;
    104108    /** Critical section protecting the heap. */
    105109    RTCRITSECT          CritSect;
     
    138142
    139143/**
     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 */
     149typedef 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;
     163AssertCompileMemberAlignment(RTHEAPPAGEBLOCKALLOCCHUNK, bmAlloc, 8);
     164AssertCompileMemberAlignment(RTHEAPPAGEBLOCKALLOCCHUNK, aBlocks, 64);
     165/** Pointer to an allocation chunk of RTHEAPPAGEBLOCKALLOCCHUNK structures. */
     166typedef 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/**
    140175 * Argument package for rtHeapPageAllocCallback.
    141176 */
     
    285320        pHeap->BlockTree            = NULL;
    286321        pHeap->fExec                = fExec;
     322        RTListInit(&pHeap->BlockAllocatorChunks);
    287323        pHeap->u32Magic             = RTHEAPPAGE_MAGIC;
    288324    }
     
    302338    pHeap->u32Magic = ~RTHEAPPAGE_MAGIC;
    303339    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 */
     349static 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 */
     400static 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();
    304419}
    305420
     
    418533            /* next */
    419534            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)
    421536                break;
    422537            iPage = ASMBitNextClear(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT, iPage);
     
    499614     * Didn't find anything, so expand the heap with a new block.
    500615     */
     616    PRTHEAPPAGEBLOCK const pBlock = rtHeapPageIntBlockAllocatorAlloc(pHeap);
     617    AssertReturn(pBlock, VERR_NO_MEMORY);
     618
    501619    RTCritSectLeave(&pHeap->CritSect);
    502620
    503621    void *pvPages = NULL;
    504622    rc = rtMemPageNativeAlloc(RTMEMPAGEPOSIX_BLOCK_SIZE, pHeap->fExec ? RTMEMPAGEALLOC_F_EXECUTABLE : 0, &pvPages);
     623
     624    RTCritSectEnter(&pHeap->CritSect);
    505625    if (RT_FAILURE(rc))
    506626    {
    507         RTCritSectEnter(&pHeap->CritSect);
     627        rtHeapPageIntBlockAllocatorFree(pHeap, pBlock);
    508628        return rc;
    509     }
    510     /** @todo Eliminate this rtMemBaseAlloc dependency! */
    511     PRTHEAPPAGEBLOCK pBlock;
    512 #ifdef RTALLOC_REPLACE_MALLOC
    513     if (g_pfnOrgMalloc)
    514         pBlock = (PRTHEAPPAGEBLOCK)g_pfnOrgMalloc(sizeof(*pBlock));
    515     else
    516 #endif
    517         pBlock = (PRTHEAPPAGEBLOCK)rtMemBaseAlloc(sizeof(*pBlock));
    518     if (!pBlock)
    519     {
    520         rtMemPageNativeFree(pvPages, RTMEMPAGEPOSIX_BLOCK_SIZE);
    521         RTCritSectEnter(&pHeap->CritSect);
    522         return VERR_NO_MEMORY;
    523629    }
    524630
     
    528634    pBlock->cFreePages      = RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
    529635    pBlock->pHeap           = pHeap;
    530 
    531     RTCritSectEnter(&pHeap->CritSect);
    532636
    533637    bool fRc = RTAvlrPVInsert(&pHeap->BlockTree, &pBlock->Core); Assert(fRc); NOREF(fRc);
     
    700804                        pBlock->Core.Key = pBlock->Core.KeyLast = NULL;
    701805                        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);
    708807
    709808                        RTCritSectEnter(&pHeap->CritSect);
Note: See TracChangeset for help on using the changeset viewer.

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