f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/* $Id$ */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** @file
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * IPRT - An Offset Based Heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * available from http://www.virtualbox.org. This file is free software;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * you can redistribute it and/or modify it under the terms of the GNU
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * General Public License (GPL) as published by the Free Software
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * The contents of this file may alternatively be used under the terms
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * of the Common Development and Distribution License Version 1.0
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * VirtualBox OSE distribution, in which case the provisions of the
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * CDDL are applicable instead of those of the GPL.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * You may elect to license modified versions of this file under the
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * terms and conditions of either the GPL or the CDDL or both.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/*******************************************************************************
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync* Header Files *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync*******************************************************************************/
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define LOG_GROUP RTLOGGROUP_DEFAULT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/heap.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include "internal/iprt.h"
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/assert.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/asm.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/err.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/log.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include <iprt/param.h>
68464669bc262783ab39e91b5a444da86b885679vboxsync#include <iprt/string.h>
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#include "internal/magics.h"
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/*******************************************************************************
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync* Structures and Typedefs *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync*******************************************************************************/
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Pointer to the heap anchor block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETINTERNAL *PRTHEAPOFFSETINTERNAL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Pointer to a heap block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETBLOCK *PRTHEAPOFFSETBLOCK;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Pointer to a free heap block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETFREE *PRTHEAPOFFSETFREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Structure describing a block in an offset based heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * If this block is allocated, it is followed by the user data.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * If this block is free, see RTHEAPOFFSETFREE.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETBLOCK
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The next block in the global block list. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETBLOCK*/ offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The previous block in the global block list. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETBLOCK*/ offPrev;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Offset into the heap of this block. Used to locate the anchor block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETINTERNAL*/ offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Flags + magic. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t fFlags;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync} RTHEAPOFFSETBLOCK;
29e82f9045a3d4eb6c3547e48725b671fadaf2cavboxsyncAssertCompileSize(RTHEAPOFFSETBLOCK, 16);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** The block is free if this flag is set. When cleared it's allocated. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_FLAGS_FREE (RT_BIT_32(0))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** The magic value. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_FLAGS_MAGIC (UINT32_C(0xabcdef00))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** The mask that needs to be applied to RTHEAPOFFSETBLOCK::fFlags to obtain the magic value. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK (~RT_BIT_32(0))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Checks if the specified block is valid or not.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns boolean answer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_IS_VALID(pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ( ((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK) == RTHEAPOFFSETBLOCK_FLAGS_MAGIC )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Checks if the specified block is valid and in use.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns boolean answer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_IS_VALID_USED(pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync == RTHEAPOFFSETBLOCK_FLAGS_MAGIC )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Checks if the specified block is valid and free.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns boolean answer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock Pointer to a RTHEAPOFFSETBLOCK structure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_IS_VALID_FREE(pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ( ((pBlock)->fFlags & (RTHEAPOFFSETBLOCK_FLAGS_MAGIC_MASK | RTHEAPOFFSETBLOCK_FLAGS_FREE)) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync == (RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE) )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Checks if the specified block is free or not.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns boolean answer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock Pointer to a valid RTHEAPOFFSETBLOCK structure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSETBLOCK_IS_FREE(pBlock) (!!((pBlock)->fFlags & RTHEAPOFFSETBLOCK_FLAGS_FREE))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * A free heap block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * This is an extended version of RTHEAPOFFSETBLOCK that takes the unused
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * user data to store free list pointers and a cached size value.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETFREE
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Core stuff. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFFSETBLOCK Core;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Pointer to the next free block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETFREE*/ offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Pointer to the previous free block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETFREE*/ offPrev;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The size of the block (excluding the RTHEAPOFFSETBLOCK part). */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** An alignment filler to make it a multiple of 16 bytes. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t Alignment;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync} RTHEAPOFFSETFREE;
29e82f9045a3d4eb6c3547e48725b671fadaf2cavboxsyncAssertCompileSize(RTHEAPOFFSETFREE, 16+16);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * The heap anchor block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * This structure is placed at the head of the memory block specified to RTHeapOffsetInit(),
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * which means that the first RTHEAPOFFSETBLOCK appears immediately after this structure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsynctypedef struct RTHEAPOFFSETINTERNAL
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The typical magic (RTHEAPOFFSET_MAGIC). */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t u32Magic;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The heap size. (This structure is included!) */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t cbHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** The amount of free memory in the heap. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t cbFree;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Free head pointer. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETFREE*/ offFreeHead;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /** Free tail pointer. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t /*PRTHEAPOFFSETFREE*/ offFreeTail;
29e82f9045a3d4eb6c3547e48725b671fadaf2cavboxsync /** Make the size of this structure 32 bytes. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uint32_t au32Alignment[3];
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync} RTHEAPOFFSETINTERNAL;
29e82f9045a3d4eb6c3547e48725b671fadaf2cavboxsyncAssertCompileSize(RTHEAPOFFSETINTERNAL, 32);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** The minimum allocation size. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSET_MIN_BLOCK (sizeof(RTHEAPOFFSETBLOCK))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncAssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETBLOCK));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncAssertCompile(RTHEAPOFFSET_MIN_BLOCK >= sizeof(RTHEAPOFFSETFREE) - sizeof(RTHEAPOFFSETBLOCK));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** The minimum and default alignment. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFFSET_ALIGNMENT (sizeof(RTHEAPOFFSETBLOCK))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/*******************************************************************************
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync* Defined Constants And Macros *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync*******************************************************************************/
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RT_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync# define RTHEAPOFFSET_STRICT 1
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Converts RTHEAPOFFSETBLOCK::offSelf into a heap anchor block pointer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns Pointer of given type.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock The block to find the heap anchor block for.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define RTHEAPOFF_GET_ANCHOR(pBlock) ( (PRTHEAPOFFSETINTERNAL)((uint8_t *)(pBlock) - (pBlock)->offSelf ) )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Converts an offset to a pointer.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * All offsets are relative to the heap to make life simple.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns Pointer of given type.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pHeapInt Pointer to the heap anchor block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param off The offset to convert.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param type The desired type.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type) ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, true /*fNull*/) )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#else
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync# define RTHEAPOFF_TO_PTR_N(pHeapInt, off, type) ( (type)((off) ? (uint8_t *)(pHeapInt) + (off) : NULL) )
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync#endif
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync/**
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * Converts an offset to a pointer.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync *
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * All offsets are relative to the heap to make life simple.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync *
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * @returns Pointer of given type.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * @param pHeapInt Pointer to the heap anchor block.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * @param off The offset to convert.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * @param type The desired type.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync */
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync#ifdef RTHEAPOFFSET_STRICT
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync# define RTHEAPOFF_TO_PTR(pHeapInt, off, type) ( (type)rtHeapOffCheckedOffToPtr(pHeapInt, off, false /*fNull*/) )
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync#else
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync# define RTHEAPOFF_TO_PTR(pHeapInt, off, type) ( (type)((uint8_t *)(pHeapInt) + (off)) )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Converts a pointer to an offset.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * All offsets are relative to the heap to make life simple.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns Offset into the heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pHeapInt Pointer to the heap anchor block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param ptr The pointer to convert.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync# define RTHEAPOFF_TO_OFF(pHeapInt, ptr) rtHeapOffCheckedPtrToOff(pHeapInt, ptr)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync# define RTHEAPOFF_TO_OFF(pHeapInt, ptr) ( (uint32_t)((ptr) ? (uintptr_t)(ptr) - (uintptr_t)(pHeapInt) : UINT32_C(0)) )
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_L(a, b) AssertMsg((a) < (b), ("a=%08x b=%08x\n", (a), (b)))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_LE(a, b) AssertMsg((a) <= (b), ("a=%08x b=%08x\n", (a), (b)))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_G(a, b) AssertMsg((a) > (b), ("a=%08x b=%08x\n", (a), (b)))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_GE(a, b) AssertMsg((a) >= (b), ("a=%08x b=%08x\n", (a), (b)))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_ALIGN(a) AssertMsg(!((uintptr_t)(a) & (RTHEAPOFFSET_ALIGNMENT - 1)), ("a=%p\n", (uintptr_t)(a)))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_PREV(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { ASSERT_ALIGN((pBlock)->offPrev); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ((pBlock)->offPrev) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync { \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE((pBlock)->offPrev, sizeof(RTHEAPOFFSETINTERNAL)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((pBlock) == (PRTHEAPOFFSETBLOCK)((pHeapInt) + 1)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_NEXT(pHeap, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { ASSERT_ALIGN((pBlock)->offNext); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ((pBlock)->offNext) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync { \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L((pBlock)->offNext, (pHeapInt)->cbHeap); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_BLOCK(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID(pBlock), ("%#x\n", (pBlock)->fFlags)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_NEXT(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_PREV(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_BLOCK_USED(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { AssertMsg(RTHEAPOFFSETBLOCK_IS_VALID_USED((pBlock)), ("%#x\n", (pBlock)->fFlags)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(RTHEAPOFF_GET_ANCHOR(pBlock) == (pHeapInt), ("%p != %p\n", RTHEAPOFF_GET_ANCHOR(pBlock), (pHeapInt))); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), sizeof(RTHEAPOFFSETINTERNAL)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L( RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->cbHeap); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_NEXT(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_PREV(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_FREE_PREV(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { ASSERT_ALIGN((pBlock)->offPrev); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ((pBlock)->offPrev) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync { \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE((pBlock)->offPrev, (pHeapInt)->offFreeHead); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L((pBlock)->offPrev, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_LE((pBlock)->offPrev, (pBlock)->Core.offPrev); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeHead, PRTHEAPOFFSETFREE) ); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_FREE_NEXT(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { ASSERT_ALIGN((pBlock)->offNext); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ((pBlock)->offNext) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync { \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_LE((pBlock)->offNext, (pHeapInt)->offFreeTail); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_G((pBlock)->offNext, RTHEAPOFF_TO_OFF(pHeapInt, pBlock)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE((pBlock)->offNext, (pBlock)->Core.offNext); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((pBlock) == RTHEAPOFF_TO_PTR(pHeapInt, (pHeapInt)->offFreeTail, PRTHEAPOFFSETFREE)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync# define ASSERT_FREE_CB(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { size_t cbCalc = ((pBlock)->Core.offNext ? (pBlock)->Core.offNext : (pHeapInt)->cbHeap) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - RTHEAPOFF_TO_OFF((pHeapInt), (pBlock)) - sizeof(RTHEAPOFFSETBLOCK); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg((pBlock)->cb == cbCalc, ("cb=%#zx cbCalc=%#zx\n", (pBlock)->cb, cbCalc)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync# define ASSERT_FREE_CB(pHeapInt, pBlock) do {} while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Asserts that a free block is valid. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_BLOCK_FREE(pHeapInt, pBlock) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { ASSERT_BLOCK(pHeapInt, &(pBlock)->Core); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(RTHEAPOFFSETBLOCK_IS_VALID_FREE(&(pBlock)->Core)); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_GE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeHead); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_LE(RTHEAPOFF_TO_OFF(pHeapInt, pBlock), (pHeapInt)->offFreeTail); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_FREE_NEXT(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_FREE_PREV(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_FREE_CB(pHeapInt, pBlock); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Asserts that the heap anchor block is ok. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#define ASSERT_ANCHOR(pHeapInt) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync do { AssertPtr(pHeapInt);\
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC); \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync } while (0)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/*******************************************************************************
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync* Internal Functions *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync*******************************************************************************/
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync/** Checked version of RTHEAPOFF_TO_PTR and RTHEAPOFF_TO_PTR_N. */
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsyncDECLINLINE(void *) rtHeapOffCheckedOffToPtr(PRTHEAPOFFSETINTERNAL pHeapInt, uint32_t off, bool fNull)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync Assert(off || fNull);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!off)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(off < pHeapInt->cbHeap, ("%#x %#x\n", off, pHeapInt->cbHeap));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt)));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return (uint8_t *)pHeapInt + off;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/** Checked version of RTHEAPOFF_TO_OFF. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncDECLINLINE(uint32_t) rtHeapOffCheckedPtrToOff(PRTHEAPOFFSETINTERNAL pHeapInt, void *pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uintptr_t off = (uintptr_t)pv - (uintptr_t)pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(off < pHeapInt->cbHeap, ("%#x %#x\n", off, pHeapInt->cbHeap));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsg(off >= sizeof(*pHeapInt), ("%#x %#x\n", off, sizeof(*pHeapInt)));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return (uint32_t)off;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif /* RTHEAPOFFSET_STRICT */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(int) RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pFree;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync unsigned i;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Validate input. The imposed minimum heap size is just a convenient value.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertReturn(cbMemory >= PAGE_SIZE, VERR_INVALID_PARAMETER);
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync AssertReturn(cbMemory < UINT32_MAX, VERR_INVALID_PARAMETER);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pvMemory, VERR_INVALID_POINTER);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertReturn((uintptr_t)pvMemory + (cbMemory - 1) > (uintptr_t)cbMemory, VERR_INVALID_PARAMETER);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Place the heap anchor block at the start of the heap memory,
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * enforce 32 byte alignment of it. Also align the heap size correctly.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = (PRTHEAPOFFSETINTERNAL)pvMemory;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ((uintptr_t)pvMemory & 31)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync const uintptr_t off = 32 - ((uintptr_t)pvMemory & 31);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbMemory -= off;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = (PRTHEAPOFFSETINTERNAL)((uintptr_t)pvMemory + off);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbMemory &= ~(RTHEAPOFFSET_ALIGNMENT - 1);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /* Init the heap anchor block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->u32Magic = RTHEAPOFFSET_MAGIC;
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync pHeapInt->cbHeap = (uint32_t)cbMemory;
0aa150e34ed49f14aaa37368c2e6999ec89e5f43vboxsync pHeapInt->cbFree = (uint32_t)cbMemory
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - sizeof(RTHEAPOFFSETBLOCK)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - sizeof(RTHEAPOFFSETINTERNAL);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = pHeapInt->offFreeHead = sizeof(*pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync for (i = 0; i < RT_ELEMENTS(pHeapInt->au32Alignment); i++)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->au32Alignment[i] = UINT32_MAX;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /* Init the single free block. */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree = RTHEAPOFF_TO_PTR(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.offNext = 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.offPrev = 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.offSelf = pHeapInt->offFreeHead;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offNext = 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offPrev = 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->cb = pHeapInt->cbFree;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *phHeap = pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetAssertAll(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return VINF_SUCCESS;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetInit);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(void *) RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt = hHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETBLOCK pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Validate and adjust the input.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pHeapInt, NULL);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (cb < RTHEAPOFFSET_MIN_BLOCK)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cb = RTHEAPOFFSET_MIN_BLOCK;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!cbAlignment)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbAlignment = RTHEAPOFFSET_ALIGNMENT;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(!(cbAlignment & (cbAlignment - 1)));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (cbAlignment < RTHEAPOFFSET_ALIGNMENT)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbAlignment = RTHEAPOFFSET_ALIGNMENT;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Do the allocation.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (RT_LIKELY(pBlock))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync void *pv = pBlock + 1;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return pv;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetAlloc);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(void *) RTHeapOffsetAllocZ(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt = hHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETBLOCK pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Validate and adjust the input.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pHeapInt, NULL);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (cb < RTHEAPOFFSET_MIN_BLOCK)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cb = RTHEAPOFFSET_MIN_BLOCK;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cb = RT_ALIGN_Z(cb, RTHEAPOFFSET_ALIGNMENT);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!cbAlignment)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbAlignment = RTHEAPOFFSET_ALIGNMENT;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(!(cbAlignment & (cbAlignment - 1)));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert((cbAlignment & ~(cbAlignment - 1)) == cbAlignment);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (cbAlignment < RTHEAPOFFSET_ALIGNMENT)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbAlignment = RTHEAPOFFSET_ALIGNMENT;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Do the allocation.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock = rtHeapOffsetAllocBlock(pHeapInt, cb, cbAlignment);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (RT_LIKELY(pBlock))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync void *pv = pBlock + 1;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync memset(pv, 0, cb);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return pv;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetAllocZ);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Allocates a block of memory from the specified heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * No parameter validation or adjustment is performed.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns Pointer to the allocated block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @returns NULL on failure.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pHeapInt The heap.
744d9da095880c872fc130e158ab664bc6526cfavboxsync * @param cb Size of the memory block to allocate.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param uAlignment The alignment specifications for the allocated block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic PRTHEAPOFFSETBLOCK rtHeapOffsetAllocBlock(PRTHEAPOFFSETINTERNAL pHeapInt, size_t cb, size_t uAlignment)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync PRTHEAPOFFSETBLOCK pRet = NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pFree;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync AssertReturn((pHeapInt)->u32Magic == RTHEAPOFFSET_MAGIC, NULL);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetAssertAll(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Search for a fitting block from the lower end of the heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync for (pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync uintptr_t offAlign;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Match for size and alignment.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->cb < cb)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync continue;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync offAlign = (uintptr_t)(&pFree->Core + 1) & (uAlignment - 1);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (offAlign)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync PRTHEAPOFFSETFREE pPrev;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync offAlign = (uintptr_t)(&pFree[1].Core + 1) & (uAlignment - 1);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync offAlign = uAlignment - offAlign;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync if (pFree->cb < cb + offAlign + sizeof(RTHEAPOFFSETFREE))
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync continue;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync /*
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * Split up the free block into two, so that the 2nd is aligned as
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * per specification.
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync */
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pPrev = pFree;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree = (PRTHEAPOFFSETFREE)((uintptr_t)(pFree + 1) + offAlign);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->Core.offPrev = pPrev->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->Core.offNext = pPrev->Core.offNext;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->offPrev = pPrev->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->offNext = pPrev->offNext;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pFree->cb = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap)
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync - pFree->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pPrev->Core.offNext = pFree->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pPrev->offNext = pFree->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pPrev->cb = pFree->Core.offSelf - pPrev->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync if (pFree->Core.offNext)
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pFree->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync if (pFree->offNext)
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync else
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pHeapInt->offFreeTail = pFree->Core.offSelf;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pHeapInt->cbFree -= sizeof(RTHEAPOFFSETBLOCK);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync ASSERT_BLOCK_FREE(pHeapInt, pPrev);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync ASSERT_BLOCK_FREE(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Split off a new FREE block?
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->cb >= cb + RT_ALIGN_Z(sizeof(RTHEAPOFFSETFREE), RTHEAPOFFSET_ALIGNMENT))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * Create a new FREE block at then end of this one.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pNew = (PRTHEAPOFFSETFREE)((uintptr_t)&pFree->Core + cb + sizeof(RTHEAPOFFSETBLOCK));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->Core.offSelf = RTHEAPOFF_TO_OFF(pHeapInt, pNew);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->Core.offNext = pFree->Core.offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->Core.offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->Core.offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->Core.fFlags = RTHEAPOFFSETBLOCK_FLAGS_MAGIC | RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->offNext = pFree->offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pNew->offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pNew->offNext, PRTHEAPOFFSETFREE)->offPrev = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->offPrev = pFree->offPrev;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pNew->offPrev)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pNew->offPrev, PRTHEAPOFFSETFREE)->offNext = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeHead = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pNew->cb = (pNew->Core.offNext ? pNew->Core.offNext : pHeapInt->cbHeap) \
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - pNew->Core.offSelf - sizeof(RTHEAPOFFSETBLOCK);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pNew);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync * Adjust and convert the old FREE node into a USED node.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.offNext = pNew->Core.offSelf;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree -= pFree->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree += pNew->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pRet = &pFree->Core;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_USED(pHeapInt, pRet);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Link it out of the free list.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->offNext, PRTHEAPOFFSETFREE)->offPrev = pFree->offPrev;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = pFree->offPrev;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->offPrev)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->offPrev, PRTHEAPOFFSETFREE)->offNext = pFree->offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeHead = pFree->offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Convert it to a used block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree -= pFree->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.fFlags &= ~RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pRet = &pFree->Core;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_USED(pHeapInt, pRet);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync break;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetAssertAll(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return pRet;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(void) RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETBLOCK pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Validate input.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtr(pv);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Get the block and heap. If in strict mode, validate these.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock = (PRTHEAPOFFSETBLOCK)pv - 1;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_USED(pHeapInt, pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_ANCHOR(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_FREE_POISON
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Poison the block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync const size_t cbBlock = (pBlock->pNext ? (uintptr_t)pBlock->pNext : (uintptr_t)pHeapInt->pvEnd)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - (uintptr_t)pBlock - sizeof(RTHEAPOFFSETBLOCK);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync memset(pBlock + 1, RTHEAPOFFSET_FREE_POISON, cbBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Call worker which does the actual job.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetFreeBlock(pHeapInt, pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Free a memory block.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync *
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pHeapInt The heap.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pBlock The memory block to free.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic void rtHeapOffsetFreeBlock(PRTHEAPOFFSETINTERNAL pHeapInt, PRTHEAPOFFSETBLOCK pBlock)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pFree = (PRTHEAPOFFSETFREE)pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pLeft;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pRight;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetAssertAll(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Look for the closest free list blocks by walking the blocks right
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * of us (both lists are sorted by address).
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync pLeft = NULL;
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync pRight = NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pHeapInt->offFreeTail)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync while (pRight && !RTHEAPOFFSETBLOCK_IS_FREE(&pRight->Core))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK(pHeapInt, &pRight->Core);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pRight = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!pRight)
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeTail, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pRight);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pLeft = RTHEAPOFF_TO_PTR_N(pHeapInt, pRight->offPrev, PRTHEAPOFFSETFREE);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pLeft)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pLeft);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertMsgReturnVoid(pLeft != pFree, ("Freed twice! pv=%p (pBlock=%p)\n", pBlock + 1, pBlock));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_L(RTHEAPOFF_TO_OFF(pHeapInt, pLeft), RTHEAPOFF_TO_OFF(pHeapInt, pFree));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(!pRight || (uintptr_t)pRight > (uintptr_t)pFree);
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync Assert(!pLeft || RTHEAPOFF_TO_PTR_N(pHeapInt, pLeft->offNext, PRTHEAPOFFSETFREE) == pRight);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Insert at the head of the free block list?
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!pLeft)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync Assert(pRight == RTHEAPOFF_TO_PTR_N(pHeapInt, pHeapInt->offFreeHead, PRTHEAPOFFSETFREE));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offPrev = 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pRight)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeHead = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Can we merge with left hand free block?
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pLeft->Core.offNext == RTHEAPOFF_TO_OFF(pHeapInt, pFree))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pLeft->Core.offNext = pFree->Core.offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pFree->Core.offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pFree->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree -= pLeft->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree = pLeft;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * No, just link it into the free list then.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.fFlags |= RTHEAPOFFSETBLOCK_FLAGS_FREE;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pRight);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pLeft);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pLeft->offNext = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pRight)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pRight->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Can we merge with right hand free block?
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if ( pRight
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync && pRight->Core.offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pFree))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /* core */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->Core.offNext = pRight->Core.offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pRight->Core.offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pRight->Core.offNext, PRTHEAPOFFSETBLOCK)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /* free */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->offNext = pRight->offNext;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (pRight->offNext)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync RTHEAPOFF_TO_PTR(pHeapInt, pRight->offNext, PRTHEAPOFFSETFREE)->offPrev = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->offFreeTail = RTHEAPOFF_TO_OFF(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree -= pRight->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Calculate the size and update free stats.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pFree->cb = (pFree->Core.offNext ? pFree->Core.offNext : pHeapInt->cbHeap)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - RTHEAPOFF_TO_OFF(pHeapInt, pFree) - sizeof(RTHEAPOFFSETBLOCK);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt->cbFree += pFree->cb;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync rtHeapOffsetAssertAll(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#ifdef RTHEAPOFFSET_STRICT
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync/**
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Internal consistency check (relying on assertions).
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * @param pHeapInt
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncstatic void rtHeapOffsetAssertAll(PRTHEAPOFFSETINTERNAL pHeapInt)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync PRTHEAPOFFSETFREE pPrev = NULL;
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync PRTHEAPOFFSETFREE pPrevFree = NULL;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_FREE(pHeapInt, pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(pBlock->offPrev == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(pPrevFree || pHeapInt->offFreeHead == RTHEAPOFF_TO_OFF(pHeapInt, pBlock));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pPrevFree = pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_USED(pHeapInt, &pBlock->Core);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(!pPrev || RTHEAPOFF_TO_OFF(pHeapInt, pPrev) == pBlock->Core.offPrev);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pPrev = pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(pHeapInt->offFreeTail == RTHEAPOFF_TO_OFF(pHeapInt, pPrevFree));
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync#endif
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(size_t) RTHeapOffsetSize(RTHEAPOFFSET hHeap, void *pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETBLOCK pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync size_t cbBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Validate input.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (!pv)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pv, 0);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertReturn(RT_ALIGN_P(pv, RTHEAPOFFSET_ALIGNMENT) == pv, 0);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Get the block and heap. If in strict mode, validate these.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock = (PRTHEAPOFFSETBLOCK)pv - 1;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = RTHEAPOFF_GET_ANCHOR(pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_BLOCK_USED(pHeapInt, pBlock);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_ANCHOR(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync Assert(pHeapInt == (PRTHEAPOFFSETINTERNAL)hHeap || !hHeap);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync /*
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync * Calculate the block size.
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync */
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync cbBlock = (pBlock->offNext ? pBlock->offNext : pHeapInt->cbHeap)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return cbBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetSize);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(size_t) RTHeapOffsetGetHeapSize(RTHEAPOFFSET hHeap)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (hHeap == NIL_RTHEAPOFFSET)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = hHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pHeapInt, 0);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_ANCHOR(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return pHeapInt->cbHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetGetHeapSize);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(size_t) RTHeapOffsetGetFreeSize(RTHEAPOFFSET hHeap)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (hHeap == NIL_RTHEAPOFFSET)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return 0;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pHeapInt = hHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync AssertPtrReturn(pHeapInt, 0);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync ASSERT_ANCHOR(pHeapInt);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync return pHeapInt->cbFree;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetGetFreeSize);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRTDECL(void) RTHeapOffsetDump(RTHEAPOFFSET hHeap, PFNRTHEAPOFFSETPRINTF pfnPrintf)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync{
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETINTERNAL pHeapInt = (PRTHEAPOFFSETINTERNAL)hHeap;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync PRTHEAPOFFSETFREE pBlock;
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pfnPrintf("**** Dumping Heap %p - cbHeap=%x cbFree=%x ****\n",
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync hHeap, pHeapInt->cbHeap, pHeapInt->cbFree);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync for (pBlock = (PRTHEAPOFFSETFREE)(pHeapInt + 1);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock;
d0e1f3c1cb2bf598991ea6448fee39f8341aed4evboxsync pBlock = RTHEAPOFF_TO_PTR_N(pHeapInt, pBlock->Core.offNext, PRTHEAPOFFSETFREE))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync {
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync size_t cb = (pBlock->offNext ? pBlock->Core.offNext : pHeapInt->cbHeap)
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync - RTHEAPOFF_TO_OFF(pHeapInt, pBlock) - sizeof(RTHEAPOFFSETBLOCK);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync if (RTHEAPOFFSETBLOCK_IS_FREE(&pBlock->Core))
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pfnPrintf("%p %06x FREE offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x : cb=%#06x offNext=%06x offPrev=%06x\n",
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb,
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock->cb, pBlock->offNext, pBlock->offPrev);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync else
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pfnPrintf("%p %06x USED offNext=%06x offPrev=%06x fFlags=%#x cb=%#06x\n",
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pBlock, pBlock->Core.offSelf, pBlock->Core.offNext, pBlock->Core.offPrev, pBlock->Core.fFlags, cb);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync }
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync pfnPrintf("**** Done dumping Heap %p ****\n", hHeap);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync}
f9f72da3edbd8434dc722c26ee038e2808d691favboxsyncRT_EXPORT_SYMBOL(RTHeapOffsetDump);
f9f72da3edbd8434dc722c26ee038e2808d691favboxsync