418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/* $Id$ */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** @file
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * IPRT - RTMemPage*, POSIX with heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/*
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync * Copyright (C) 2006-2012 Oracle Corporation
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * available from http://www.virtualbox.org. This file is free software;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * you can redistribute it and/or modify it under the terms of the GNU
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * General Public License (GPL) as published by the Free Software
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * The contents of this file may alternatively be used under the terms
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * of the Common Development and Distribution License Version 1.0
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * VirtualBox OSE distribution, in which case the provisions of the
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * CDDL are applicable instead of those of the GPL.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * You may elect to license modified versions of this file under the
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * terms and conditions of either the GPL or the CDDL or both.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/*******************************************************************************
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync* Header Files *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync*******************************************************************************/
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include "internal/iprt.h"
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/mem.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/asm.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/assert.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/avl.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/critsect.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/err.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/once.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/param.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <iprt/string.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include "internal/mem.h"
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync#include "../alloc-ef.h"
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <stdlib.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <errno.h>
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#include <sys/mman.h>
cac913354e477e731cfcdecfbe6595c26105cac3vboxsync#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
cac913354e477e731cfcdecfbe6595c26105cac3vboxsync# define MAP_ANONYMOUS MAP_ANON
cac913354e477e731cfcdecfbe6595c26105cac3vboxsync#endif
cac913354e477e731cfcdecfbe6595c26105cac3vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/*******************************************************************************
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync* Defined Constants And Macros *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync*******************************************************************************/
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** Threshold at which to we switch to simply calling mmap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#define RTMEMPAGEPOSIX_MMAP_THRESHOLD _128K
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** The size of a heap block (power of two) - in bytes. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#define RTMEMPAGEPOSIX_BLOCK_SIZE _2M
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncAssertCompile(RTMEMPAGEPOSIX_BLOCK_SIZE == (RTMEMPAGEPOSIX_BLOCK_SIZE / PAGE_SIZE) * PAGE_SIZE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** The number of pages per heap block. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#define RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT (RTMEMPAGEPOSIX_BLOCK_SIZE / PAGE_SIZE)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/*******************************************************************************
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync* Structures and Typedefs *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync*******************************************************************************/
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** Pointer to a page heap block. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsynctypedef struct RTHEAPPAGEBLOCK *PRTHEAPPAGEBLOCK;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * A simple page heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsynctypedef struct RTHEAPPAGE
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Magic number (RTHEAPPAGE_MAGIC). */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t u32Magic;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The number of pages in the heap (in BlockTree). */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cHeapPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The number of currently free pages. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cFreePages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Number of successful calls. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cAllocCalls;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Number of successful free calls. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cFreeCalls;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The free call number at which we last tried to minimize the heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t uLastMinimizeCall;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Tree of heap blocks. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AVLRPVTREE BlockTree;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Allocation hint no 1 (last freed). */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGEBLOCK pHint1;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Allocation hint no 2 (last alloc). */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGEBLOCK pHint2;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Critical section protecting the heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCRITSECT CritSect;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Set if the memory must allocated with execute access. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync bool fExec;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync} RTHEAPPAGE;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync#define RTHEAPPAGE_MAGIC UINT32_C(0xfeedface)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** Pointer to a page heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsynctypedef RTHEAPPAGE *PRTHEAPPAGE;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Describes a page heap block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsynctypedef struct RTHEAPPAGEBLOCK
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The AVL tree node core (void pointer range). */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AVLRPVNODECORE Core;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Allocation bitmap. Set bits marks allocated pages. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t bmAlloc[RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT / 32];
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Allocation boundrary bitmap. Set bits marks the start of
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * allocations. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t bmFirst[RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT / 32];
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The number of free pages. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cFreePages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Pointer back to the heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGE pHeap;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync} RTHEAPPAGEBLOCK;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Argument package for rtHeapPageAllocCallback.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsynctypedef struct RTHEAPPAGEALLOCARGS
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** The number of pages to allocate. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync size_t cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Non-null on success. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync void *pvAlloc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** Whether the pages should be zeroed or not. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync bool fZero;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync} RTHEAPPAGEALLOCARGS;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/*******************************************************************************
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync* Global Variables *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync*******************************************************************************/
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** Initialize once structure. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic RTONCE g_MemPagePosixInitOnce = RTONCE_INITIALIZER;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** The page heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic RTHEAPPAGE g_MemPagePosixHeap;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/** The exec page heap. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic RTHEAPPAGE g_MemExecPosixHeap;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync#ifdef RT_OS_OS2
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync/*
64eea8161bef2aa3c6516481383c830bca27abfevboxsync * A quick mmap/munmap mockup for avoid duplicating lots of good code.
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync */
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync# define INCL_BASE
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync# include <os2.h>
64eea8161bef2aa3c6516481383c830bca27abfevboxsync# undef MAP_PRIVATE
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync# define MAP_PRIVATE 0
64eea8161bef2aa3c6516481383c830bca27abfevboxsync# undef MAP_ANONYMOUS
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync# define MAP_ANONYMOUS 0
444552428dda68013130a3af91af19bdbeebb616vboxsync# undef MAP_FAILED
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync# define MAP_FAILED (void *)-1
17b787f1934a41d6d621a5f3c2eab63483bfc5abvboxsync# undef mmap
64eea8161bef2aa3c6516481383c830bca27abfevboxsync# define mmap iprt_mmap
17b787f1934a41d6d621a5f3c2eab63483bfc5abvboxsync# undef munmap
64eea8161bef2aa3c6516481383c830bca27abfevboxsync# define munmap iprt_munmap
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsyncstatic void *mmap(void *pvWhere, size_t cb, int fProt, int fFlags, int fd, off_t off)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync{
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync NOREF(pvWhere); NOREF(fd); NOREF(off);
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync void *pv = NULL;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync ULONG fAlloc = OBJ_ANY | PAG_COMMIT;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync if (fProt & PROT_EXEC)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync fAlloc |= PAG_EXECUTE;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync if (fProt & PROT_READ)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync fAlloc |= PAG_READ;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync if (fProt & PROT_WRITE)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync fAlloc |= PAG_WRITE;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync APIRET rc = DosAllocMem(&pv, cb, fAlloc);
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync if (rc == NO_ERROR)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync return pv;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync errno = ENOMEM;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync return MAP_FAILED;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync}
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsyncstatic int munmap(void *pv, size_t cb)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync{
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync APIRET rc = DosFreeMem(pv);
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync if (rc == NO_ERROR)
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync return 0;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync errno = EINVAL;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync return -1;
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync}
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync#endif
7afb422516a7a70d0f0e58f3d81affdd62bc471fvboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Initializes the heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The page heap to initialize.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fExec Whether the heap memory should be marked as
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * executable or not.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncint RTHeapPageInit(PRTHEAPPAGE pHeap, bool fExec)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = RTCritSectInitEx(&pHeap->CritSect,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCRITSECT_FLAGS_NO_LOCK_VAL | RTCRITSECT_FLAGS_NO_NESTING | RTCRITSECT_FLAGS_BOOTSTRAP_HACK,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, NULL);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cHeapPages = 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreePages = 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cAllocCalls = 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreeCalls = 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->uLastMinimizeCall = 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->BlockTree = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->fExec = fExec;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->u32Magic = RTHEAPPAGE_MAGIC;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync * Deletes the heap and all the memory it tracks.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The page heap to delete.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncint RTHeapPageDelete(PRTHEAPPAGE pHeap)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync NOREF(pHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VERR_NOT_IMPLEMENTED;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Avoids some gotos in rtHeapPageAllocFromBlock.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns VINF_SUCCESS.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pBlock The block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param iPage The page to start allocating at.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The number of pages.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fZero Whether to clear them.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param ppv Where to return the allocation address.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncDECLINLINE(int) rtHeapPageAllocFromBlockSuccess(PRTHEAPPAGEBLOCK pBlock, uint32_t iPage, size_t cPages, bool fZero, void **ppv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGE pHeap = pBlock->pHeap;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync ASMBitSet(&pBlock->bmFirst[0], iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->cFreePages -= cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreePages -= cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pHeap->pHint2 || pHeap->pHint2->cFreePages < pBlock->cFreePages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->pHint2 = pBlock;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cAllocCalls++;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync void *pv = (uint8_t *)pBlock->Core.Key + (iPage << PAGE_SHIFT);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *ppv = pv;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (fZero)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RT_BZERO(pv, cPages << PAGE_SHIFT);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VINF_SUCCESS;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Checks if a page range is free in the specified block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns @c true if the range is free, @c false if not.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pBlock The block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param iFirst The first page to check.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The number of pages to check.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncDECLINLINE(bool) rtHeapPageIsPageRangeFree(PRTHEAPPAGEBLOCK pBlock, uint32_t iFirst, uint32_t cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t i = iFirst + cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync while (i-- > iFirst)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (ASMBitTest(&pBlock->bmAlloc[0], i))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return false;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(!ASMBitTest(&pBlock->bmFirst[0], i));
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return true;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Tries to allocate a chunk of pages from a heap block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @retval VINF_SUCCESS on success.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @retval VERR_NO_MEMORY if the allocation failed.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pBlock The block to allocate from.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The size of the allocation.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fZero Whether it should be zeroed or not.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param ppv Where to return the allocation address on success.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncDECLINLINE(int) rtHeapPageAllocFromBlock(PRTHEAPPAGEBLOCK pBlock, size_t cPages, bool fZero, void **ppv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pBlock->cFreePages >= cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int iPage = ASMBitFirstClear(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(iPage >= 0);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* special case: single page. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (cPages == 1)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync ASMBitSet(&pBlock->bmAlloc[0], iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtHeapPageAllocFromBlockSuccess(pBlock, iPage, cPages, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync while ( iPage >= 0
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync && (unsigned)iPage <= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT - cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (rtHeapPageIsPageRangeFree(pBlock, iPage + 1, cPages - 1))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync ASMBitSetRange(&pBlock->bmAlloc[0], iPage, iPage + cPages);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtHeapPageAllocFromBlockSuccess(pBlock, iPage, cPages, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* next */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync iPage = ASMBitNextSet(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT, iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (iPage < 0 || iPage >= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT - 1)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync break;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync iPage = ASMBitNextClear(&pBlock->bmAlloc[0], RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT, iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VERR_NO_MEMORY;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * RTAvlrPVDoWithAll callback.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns 0 to continue the enum, non-zero to quit it.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pNode The node.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pvUser The user argument.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic DECLCALLBACK(int) rtHeapPageAllocCallback(PAVLRPVNODECORE pNode, void *pvUser)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGEBLOCK pBlock = RT_FROM_MEMBER(pNode, RTHEAPPAGEBLOCK, Core);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTHEAPPAGEALLOCARGS *pArgs = (RTHEAPPAGEALLOCARGS *)pvUser;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = rtHeapPageAllocFromBlock(pBlock, pArgs->cPages, pArgs->fZero, &pArgs->pvAlloc);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return RT_SUCCESS(rc) ? 1 : 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Worker for RTHeapPageAlloc.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The heap - locked.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The page count.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pszTag The tag.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fZero Whether to zero the memory.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param ppv Where to return the address of the allocation
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * on success.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic int rtHeapPageAllocLocked(PRTHEAPPAGE pHeap, size_t cPages, const char *pszTag, bool fZero, void **ppv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc;
4e47bb772df0d04d1ded3e06354de547d52e2d06vboxsync NOREF(pszTag);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Use the hints first.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pHeap->pHint1)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = rtHeapPageAllocFromBlock(pHeap->pHint1, cPages, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (rc != VERR_NO_MEMORY)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pHeap->pHint2)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = rtHeapPageAllocFromBlock(pHeap->pHint2, cPages, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (rc != VERR_NO_MEMORY)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Search the heap for a block with enough free space.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * N.B. This search algorithm is not optimal at all. What (hopefully) saves
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * it are the two hints above.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pHeap->cFreePages >= cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTHEAPPAGEALLOCARGS Args;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Args.cPages = cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Args.pvAlloc = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Args.fZero = fZero;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTAvlrPVDoWithAll(&pHeap->BlockTree, true /*fFromLeft*/, rtHeapPageAllocCallback, &Args);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (Args.pvAlloc)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *ppv = Args.pvAlloc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VINF_SUCCESS;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Didn't find anytyhing, so expand the heap with a new block.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectLeave(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync void *pvPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pvPages = mmap(NULL, RTMEMPAGEPOSIX_BLOCK_SIZE,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PROT_READ | PROT_WRITE | (pHeap->fExec ? PROT_EXEC : 0),
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync MAP_PRIVATE | MAP_ANONYMOUS,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync -1, 0);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pvPages == MAP_FAILED)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return RTErrConvertFromErrno(errno);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /** @todo Eliminate this rtMemBaseAlloc dependency! */
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync PRTHEAPPAGEBLOCK pBlock;
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync#ifdef RTALLOC_REPLACE_MALLOC
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync if (g_pfnOrgMalloc)
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync pBlock = (PRTHEAPPAGEBLOCK)g_pfnOrgMalloc(sizeof(*pBlock));
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync else
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync#endif
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync pBlock = (PRTHEAPPAGEBLOCK)rtMemBaseAlloc(sizeof(*pBlock));
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pBlock)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync munmap(pvPages, RTMEMPAGEPOSIX_BLOCK_SIZE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VERR_NO_MEMORY;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RT_ZERO(*pBlock);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->Core.Key = pvPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->Core.KeyLast = (uint8_t *)pvPages + RTMEMPAGEPOSIX_BLOCK_SIZE - 1;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->cFreePages = RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->pHeap = pHeap;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync bool fRc = RTAvlrPVInsert(&pHeap->BlockTree, &pBlock->Core); Assert(fRc); NOREF(fRc);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreePages += RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cHeapPages += RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Grab memory from the new block (cannot fail).
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = rtHeapPageAllocFromBlock(pBlock, cPages, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(rc == VINF_SUCCESS);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Allocates one or more pages off the heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The page heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The number of pages to allocate.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pszTag The allocation tag.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fZero Set if the pages should be zeroed or not.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param ppv Where to return the pointer to the pages.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncint RTHeapPageAlloc(PRTHEAPPAGE pHeap, size_t cPages, const char *pszTag, bool fZero, void **ppv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Validate input.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertPtr(ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *ppv = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertPtrReturn(pHeap, VERR_INVALID_HANDLE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertReturn(pHeap->u32Magic == RTHEAPPAGE_MAGIC, VERR_INVALID_HANDLE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertMsgReturn(cPages < RTMEMPAGEPOSIX_BLOCK_SIZE, ("%#zx\n", cPages), VERR_OUT_OF_RANGE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Grab the lock and call a worker with many returns.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = rtHeapPageAllocLocked(pHeap, cPages, pszTag, fZero, ppv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectLeave(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * RTAvlrPVDoWithAll callback.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns 0 to continue the enum, non-zero to quit it.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pNode The node.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pvUser Pointer to a block pointer variable. For returning
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * the address of the block to be freed.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic DECLCALLBACK(int) rtHeapPageFindUnusedBlockCallback(PAVLRPVNODECORE pNode, void *pvUser)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGEBLOCK pBlock = RT_FROM_MEMBER(pNode, RTHEAPPAGEBLOCK, Core);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pBlock->cFreePages == RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *(PRTHEAPPAGEBLOCK *)pvUser = pBlock;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return 1;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return 0;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Allocates one or more pages off the heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The page heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pv Pointer to what RTHeapPageAlloc returned.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cPages The number of pages that was allocated.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncint RTHeapPageFree(PRTHEAPPAGE pHeap, void *pv, size_t cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Validate input.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return VINF_SUCCESS;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertPtrReturn(pHeap, VERR_INVALID_HANDLE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertReturn(pHeap->u32Magic == RTHEAPPAGE_MAGIC, VERR_INVALID_HANDLE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Grab the lock and look up the page.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PRTHEAPPAGEBLOCK pBlock = (PRTHEAPPAGEBLOCK)RTAvlrPVRangeGet(&pHeap->BlockTree, pv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pBlock)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Validate the specified address range.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t const iPage = (uint32_t)(((uintptr_t)pv - (uintptr_t)pBlock->Core.Key) >> PAGE_SHIFT);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* Check the range is within the block. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync bool fOk = iPage + cPages <= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* Check that it's the start of an allocation. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync fOk = fOk && ASMBitTest(&pBlock->bmFirst[0], iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* Check that the range ends at an allocation boundrary. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync fOk = fOk && ( iPage + cPages == RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync || ASMBitTest(&pBlock->bmFirst[0], iPage + cPages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync || !ASMBitTest(&pBlock->bmAlloc[0], iPage + cPages));
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /* Check the other pages. */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t const iLastPage = iPage + cPages - 1;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync for (uint32_t i = iPage + 1; i < iLastPage && fOk; i++)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync fOk = ASMBitTest(&pBlock->bmAlloc[0], i)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync && !ASMBitTest(&pBlock->bmFirst[0], i);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (fOk)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Free the memory.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync ASMBitClearRange(&pBlock->bmAlloc[0], iPage, iPage + cPages);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync ASMBitClear(&pBlock->bmFirst[0], iPage);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->cFreePages += cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreePages += cPages;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreeCalls++;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pHeap->pHint1 || pHeap->pHint1->cFreePages < pBlock->cFreePages)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->pHint1 = pBlock;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Shrink the heap. Not very efficient because of the AVL tree.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if ( pHeap->cFreePages >= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT * 3
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync && pHeap->cFreePages >= pHeap->cHeapPages / 2 /* 50% free */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync && pHeap->cFreeCalls - pHeap->uLastMinimizeCall > RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync )
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync uint32_t cFreePageTarget = pHeap->cHeapPages / 4; /* 25% free */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync while (pHeap->cFreePages > cFreePageTarget)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->uLastMinimizeCall = pHeap->cFreeCalls;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTAvlrPVDoWithAll(&pHeap->BlockTree, false /*fFromLeft*/,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rtHeapPageFindUnusedBlockCallback, &pBlock);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pBlock)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync break;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync void *pv2 = RTAvlrPVRemove(&pHeap->BlockTree, pBlock->Core.Key); Assert(pv2); NOREF(pv2);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cHeapPages -= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->cFreePages -= RTMEMPAGEPOSIX_BLOCK_PAGE_COUNT;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->pHint1 = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pHeap->pHint2 = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectLeave(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync munmap(pBlock->Core.Key, RTMEMPAGEPOSIX_BLOCK_SIZE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->Core.Key = pBlock->Core.KeyLast = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pBlock->cFreePages = 0;
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync#ifdef RTALLOC_REPLACE_MALLOC
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync if (g_pfnOrgFree)
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync g_pfnOrgFree(pBlock);
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync else
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync#endif
44bd3d3cc274af9c8521e3b39217d6edd0857130vboxsync rtMemBaseFree(pBlock);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectEnter(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync else
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = VERR_INVALID_POINTER;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync else
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = VERR_INVALID_POINTER;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTCritSectLeave(&pHeap->CritSect);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Initializes the heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns IPRT status code
a438caaf732f7839dc66b4f8dad672527845a003vboxsync * @param pvUser Unused.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
a438caaf732f7839dc66b4f8dad672527845a003vboxsyncstatic DECLCALLBACK(int) rtMemPagePosixInitOnce(void *pvUser)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
a438caaf732f7839dc66b4f8dad672527845a003vboxsync NOREF(pvUser);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = RTHeapPageInit(&g_MemPagePosixHeap, false /*fExec*/);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = RTHeapPageInit(&g_MemExecPosixHeap, true /*fExec*/);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RTHeapPageDelete(&g_MemPagePosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rc;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Allocates memory from the specified heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @returns Address of the allocated memory.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cb The number of bytes to allocate.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pszTag The tag.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param fZero Whether to zero the memory or not.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The heap to use.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic void *rtMemPagePosixAlloc(size_t cb, const char *pszTag, bool fZero, PRTHEAPPAGE pHeap)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Validate & adjust the input.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(cb > 0);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync NOREF(pszTag);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * If the allocation is relatively large, we use mmap/munmap directly.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync void *pv;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (cb >= RTMEMPAGEPOSIX_MMAP_THRESHOLD)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pv = mmap(NULL, cb,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync PROT_READ | PROT_WRITE | (pHeap == &g_MemExecPosixHeap ? PROT_EXEC : 0),
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync MAP_PRIVATE | MAP_ANONYMOUS,
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync -1, 0);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (pv != MAP_FAILED)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertPtr(pv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (fZero)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync RT_BZERO(pv, cb);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync else
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pv = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync else
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
a438caaf732f7839dc66b4f8dad672527845a003vboxsync int rc = RTOnce(&g_MemPagePosixInitOnce, rtMemPagePosixInitOnce, NULL);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_SUCCESS(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync rc = RTHeapPageAlloc(pHeap, cb >> PAGE_SHIFT, pszTag, fZero, &pv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (RT_FAILURE(rc))
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync pv = NULL;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return pv;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync/**
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Free memory allocated by rtMemPagePosixAlloc.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync *
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pv The address of the memory to free.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param cb The size.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * @param pHeap The heap.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncstatic void rtMemPagePosixFree(void *pv, size_t cb, PRTHEAPPAGE pHeap)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * Validate & adjust the input.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (!pv)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return;
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertPtr(pv);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(cb > 0);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync Assert(!((uintptr_t)pv & PAGE_OFFSET_MASK));
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync cb = RT_ALIGN_Z(cb, PAGE_SIZE);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync /*
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync * If the allocation is relatively large, we use mmap/munmap directly.
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync */
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync if (cb >= RTMEMPAGEPOSIX_MMAP_THRESHOLD)
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = munmap(pv, cb);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertMsg(rc == 0, ("rc=%d pv=%p cb=%#zx\n", rc, pv, cb)); NOREF(rc);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync else
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync {
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync int rc = RTHeapPageFree(pHeap, pv, cb >> PAGE_SHIFT);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync AssertRC(rc);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync }
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncRTDECL(void *) RTMemPageAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtMemPagePosixAlloc(cb, pszTag, false /*fZero*/, &g_MemPagePosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncRTDECL(void *) RTMemPageAllocZTag(size_t cb, const char *pszTag) RT_NO_THROW
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtMemPagePosixAlloc(cb, pszTag, true /*fZero*/, &g_MemPagePosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncRTDECL(void) RTMemPageFree(void *pv, size_t cb) RT_NO_THROW
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtMemPagePosixFree(pv, cb, &g_MemPagePosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncRTDECL(void *) RTMemExecAllocTag(size_t cb, const char *pszTag) RT_NO_THROW
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtMemPagePosixAlloc(cb, pszTag, false /*fZero*/, &g_MemExecPosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsyncRTDECL(void) RTMemExecFree(void *pv, size_t cb) RT_NO_THROW
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync{
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync return rtMemPagePosixFree(pv, cb, &g_MemExecPosixHeap);
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync}
418b9db49fbc652ef9c3f030fdc0f1a322403d95vboxsync