474 lines
17 KiB
C
474 lines
17 KiB
C
|
/* **********************************************************
|
||
|
* Copyright 1998 - 2010 VMware, Inc. All rights reserved.
|
||
|
* **********************************************************/
|
||
|
|
||
|
/*
|
||
|
* @VMKAPIMOD_LICENSE@
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* Heap */ /**
|
||
|
* \addtogroup Core
|
||
|
* @{
|
||
|
* \defgroup Heap Heaps
|
||
|
*
|
||
|
* vmkernel has local heaps to help isolate VMKernel subsystems from
|
||
|
* one another. Benefits include:
|
||
|
* \li Makes it easier to track per-subssystem memory consumption,
|
||
|
* enforce a cap on how much memory a given subsystem can allocate,
|
||
|
* locate the origin of memory leaks, ...
|
||
|
* \li Confines most memory corruptions to the guilty subsystem.
|
||
|
*
|
||
|
* @{
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
|
||
|
#ifndef _VMKAPI_HEAP_H_
|
||
|
#define _VMKAPI_HEAP_H_
|
||
|
|
||
|
/** \cond never */
|
||
|
#ifndef VMK_HEADER_INCLUDED_FROM_VMKAPI_H
|
||
|
#error This vmkapi file should never be included directly but only via vmkapi.h
|
||
|
#endif
|
||
|
/** \endcond never */
|
||
|
|
||
|
#define VMK_INVALID_HEAP_ID NULL
|
||
|
|
||
|
typedef struct Heap* vmk_HeapID;
|
||
|
|
||
|
/**
|
||
|
* \brief Types of heaps.
|
||
|
*/
|
||
|
typedef enum {
|
||
|
/**
|
||
|
* \brief Heaps that get their own memory pool.
|
||
|
*
|
||
|
* Heaps of type VMK_HEAP_TYPE_SIMPLE get memory of type
|
||
|
* VMK_MEM_PHYS_ANY_CONTIGUITY and VMK_PHYS_ADDR_ANY, which are suitable
|
||
|
* for purely software heaps, and may be suitable for some heaps that
|
||
|
* need to be addressable by hardware. A new memory pool will be
|
||
|
* constructed for this heap. VMK_HEAP_TYPE_CUSTOM or VMK_HEAP_TYPE_MEMPOOL
|
||
|
* must be used in order to specify different contiguity or physical
|
||
|
* constraints, or to use an existing memory pool.
|
||
|
*/
|
||
|
VMK_HEAP_TYPE_SIMPLE = 0,
|
||
|
|
||
|
/** \brief Heaps that can customize additional parameters. */
|
||
|
VMK_HEAP_TYPE_CUSTOM = 1,
|
||
|
|
||
|
/** \brief Heaps whose memory comes from a specified memPool. */
|
||
|
VMK_HEAP_TYPE_MEMPOOL = 2,
|
||
|
} vmk_HeapType;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Properties for creating a heap allocator.
|
||
|
*/
|
||
|
typedef struct vmk_HeapCreateProps {
|
||
|
/** \brief Type of heap. */
|
||
|
vmk_HeapType type;
|
||
|
|
||
|
/** \brief Name associated with this heap. */
|
||
|
vmk_Name name;
|
||
|
|
||
|
/** \brief Module ID of the module creating this heap. */
|
||
|
vmk_ModuleID module;
|
||
|
|
||
|
/** \brief Initial size of the heap in bytes. */
|
||
|
vmk_ByteCountSmall initial;
|
||
|
|
||
|
/** \brief Maximum size of the heap in bytes. */
|
||
|
vmk_ByteCountSmall max;
|
||
|
|
||
|
/** \brief How long to wait for memory during heap creation. */
|
||
|
vmk_uint32 creationTimeoutMS;
|
||
|
|
||
|
/** \brief Type-specific heap properties. */
|
||
|
union {
|
||
|
/** \brief Properties for VMK_HEAP_TYPE_CUSTOM. */
|
||
|
struct {
|
||
|
/** \brief Physical contiguity allocated from this heap. */
|
||
|
vmk_MemPhysContiguity physContiguity;
|
||
|
|
||
|
/** \brief Physical address resrictions. */
|
||
|
vmk_MemPhysAddrConstraint physRange;
|
||
|
} custom;
|
||
|
|
||
|
/** \brief Properties for VMK_HEAP_TYPE_MEMPOOL. */
|
||
|
struct {
|
||
|
/** \brief Physical contiguity allocated from this heap. */
|
||
|
vmk_MemPhysContiguity physContiguity;
|
||
|
|
||
|
/** \brief Physical address resrictions. */
|
||
|
vmk_MemPhysAddrConstraint physRange;
|
||
|
|
||
|
/** \brief Memory pool to back this heap. */
|
||
|
vmk_MemPool memPool;
|
||
|
} memPool;
|
||
|
} typeSpecific;
|
||
|
} vmk_HeapCreateProps;
|
||
|
|
||
|
/**
|
||
|
* \brief Structure for querying properties of a heap.
|
||
|
*/
|
||
|
typedef struct vmk_HeapGetProps {
|
||
|
/** \brief Name associated with this heap. */
|
||
|
vmk_Name name;
|
||
|
|
||
|
/** \brief Module ID of the module that created this heap. */
|
||
|
vmk_ModuleID module;
|
||
|
|
||
|
/** \brief Initial size of the heap in bytes. */
|
||
|
vmk_ByteCountSmall initial;
|
||
|
|
||
|
/** \brief Maximum size of the heap in bytes. */
|
||
|
vmk_ByteCountSmall max;
|
||
|
|
||
|
/** \brief Physical contiguity allocated from this heap. */
|
||
|
vmk_MemPhysContiguity physContiguity;
|
||
|
|
||
|
/** \brief Physical address resrictions. */
|
||
|
vmk_MemPhysAddrConstraint physRange;
|
||
|
|
||
|
/** \brief Memory pool backing this heap. */
|
||
|
vmk_MemPool memPool;
|
||
|
} vmk_HeapGetProps;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \brief Describes characteristics of allocation from a heap.
|
||
|
*/
|
||
|
typedef struct vmk_HeapAllocationDescriptor {
|
||
|
/** \brief The size of the object being allocated. */
|
||
|
vmk_ByteCount size;
|
||
|
/** \brief The alignment at which these objects will be allocated. */
|
||
|
vmk_ByteCount alignment;
|
||
|
/** \brief The number of objects of this size and alignment being allocated. */
|
||
|
vmk_uint64 count;
|
||
|
} vmk_HeapAllocationDescriptor;
|
||
|
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapCreate -- */ /**
|
||
|
*
|
||
|
* \brief Create a heap that can grow dynamically up to the max size.
|
||
|
*
|
||
|
* \note This function may block if heapCreationTimeoutMS is not
|
||
|
* VMK_TIMEOUT_NONBLOCKING.
|
||
|
*
|
||
|
* \param[in] props Properties of the heap.
|
||
|
* \param[out] heapID Newly created heap or VMK_INVALID_HEAP_ID
|
||
|
* on failure.
|
||
|
*
|
||
|
* \retval VMK_NO_MEM The heap could not be allocated.
|
||
|
* \retval VMK_BAD_PARAM Invalid combination of props->initial and props->max
|
||
|
* was specified.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
VMK_ReturnStatus vmk_HeapCreate(vmk_HeapCreateProps *props,
|
||
|
vmk_HeapID *heapID);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapDestroy -- */ /**
|
||
|
*
|
||
|
* \brief Destroy a dynamic heap
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] heap Heap to destroy.
|
||
|
*
|
||
|
* \pre All memory allocated on the heap should be freed before the heap
|
||
|
* is destroyed.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void vmk_HeapDestroy(vmk_HeapID heap);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapFree -- */ /**
|
||
|
*
|
||
|
* \brief Free memory allocated with vmk_HeapAlloc.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] heap Heap that memory to be freed was allocated from.
|
||
|
* \param[in] mem Memory to be freed. Should not be NULL.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void vmk_HeapFree(vmk_HeapID heap, void *mem);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAllocWithRA -- */ /**
|
||
|
*
|
||
|
* \brief Allocate memory and specify the caller's address.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* This is useful when allocating memory from a wrapper function.
|
||
|
*
|
||
|
* \param[in] heap Heap that memory to be freed was allocated from.
|
||
|
* \param[in] size Number of bytes to allocate.
|
||
|
* \param[in] ra Address to return to.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void *vmk_HeapAllocWithRA(vmk_HeapID heap, vmk_uint32 size, void *ra);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAlignWithRA -- */ /**
|
||
|
*
|
||
|
* \brief Allocate aligned memory and specify the caller's address
|
||
|
*
|
||
|
* This is useful when allocating memory from a wrapper function.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] heap Heap that memory to be freed was allocated from.
|
||
|
* \param[in] size Number of bytes to allocate.
|
||
|
* \param[in] align Number of bytes the allocation should be aligned
|
||
|
* on.
|
||
|
* \param[in] ra Address to return to after allocation.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void *vmk_HeapAlignWithRA(vmk_HeapID heap, vmk_uint32 size,
|
||
|
vmk_uint32 align, void *ra);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAlloc -- */ /**
|
||
|
*
|
||
|
* \brief Allocate memory in the specified heap
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] _heap Heap to allocate from.
|
||
|
* \param[in] _size Number of bytes to allocate.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
#define vmk_HeapAlloc(_heap, _size) \
|
||
|
(vmk_HeapAllocWithRA((_heap), (_size), __builtin_return_address(0)))
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAlign -- */ /**
|
||
|
*
|
||
|
* \brief Allocate aligned memory
|
||
|
*
|
||
|
* \param[in] _heap Heap to allocate from.
|
||
|
* \param[in] _size Number of bytes to allocate.
|
||
|
* \param[in] _alignment Number of bytes the allocation should be
|
||
|
* aligned on.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
#define vmk_HeapAlign(_heap, _size, _alignment) \
|
||
|
(vmk_HeapAlignWithRA((_heap), (_size), (_alignment), \
|
||
|
__builtin_return_address(0)))
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAllocWithTimeoutAndRA -- */ /**
|
||
|
*
|
||
|
* \brief Allocate memory, possibly waiting for physical memory.
|
||
|
*
|
||
|
* If the heap is not already at maximum size, this call may block
|
||
|
* for up to timeoutMS milliseconds for memory to become available
|
||
|
* to grow the heap. If the heap is full and is already at maximum
|
||
|
* size, no blocking will be performed.
|
||
|
*
|
||
|
* This is useful when allocating memory from a wrapper function.
|
||
|
*
|
||
|
* \note This function may block.
|
||
|
*
|
||
|
* \param[in] heap Heap to allocate from.
|
||
|
* \param[in] size Number of bytes to allocate.
|
||
|
* \param[in] timeoutMS Maximum wait time in milliseconds.
|
||
|
* \param[in] ra Address to return to.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void *vmk_HeapAllocWithTimeoutAndRA(vmk_HeapID heap, vmk_uint32 size,
|
||
|
vmk_uint32 timeoutMS, void *ra);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAlignWithTimeoutAndRA -- */ /**
|
||
|
*
|
||
|
* \brief Allocate aligned memory, possibly waiting for physical memory.
|
||
|
*
|
||
|
* If the heap is not already at maximum size, this call may block
|
||
|
* for up to timeoutMS milliseconds for memory to become available
|
||
|
* to grow the heap. If the heap is full and is already at maximum
|
||
|
* size, no blocking will be performed.
|
||
|
*
|
||
|
* This is useful when allocating memory from a wrapper function.
|
||
|
*
|
||
|
* \note This function may block.
|
||
|
*
|
||
|
* \param[in] heap Heap to allocate from.
|
||
|
* \param[in] size Number of bytes to allocate.
|
||
|
* \param[in] align Number of bytes the allocation should be
|
||
|
* aligned on.
|
||
|
* \param[in] timeoutMS Maximum wait time in milliseconds.
|
||
|
* \param[in] ra Address to return to after allocation.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
void *vmk_HeapAlignWithTimeoutAndRA(vmk_HeapID heap, vmk_uint32 size,
|
||
|
vmk_uint32 align, vmk_uint32 timeoutMS,
|
||
|
void *ra);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAllocWithTimeout -- */ /**
|
||
|
*
|
||
|
* \brief Allocate memory, possibly waiting for physical memory.
|
||
|
*
|
||
|
* If the heap is not already at maximum size, this call may block
|
||
|
* for up to timeoutMS milliseconds for memory to become available
|
||
|
* to grow the heap. If the heap is full and is already at maximum
|
||
|
* size, no blocking will be performed.
|
||
|
*
|
||
|
* \note This function may block.
|
||
|
*
|
||
|
* \param[in] _heap Heap to allocate from.
|
||
|
* \param[in] _size Number of bytes to allocate.
|
||
|
* \param[in] _timeoutMS Maximum wait time in milliseconds.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
#define vmk_HeapAllocWithTimeout(_heap, _size, _timeoutMS) \
|
||
|
(vmk_HeapAllocWithTimeoutAndRA((_heap), (_size), (_timeoutMS), \
|
||
|
__builtin_return_address(0)))
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapAlignWithTimeout -- */ /**
|
||
|
*
|
||
|
* \brief Allocate aligned memory, possibly waiting for physical memory.
|
||
|
*
|
||
|
* If the heap is not already at maximum size, this call may block
|
||
|
* for up to timeoutMS milliseconds for memory to become available
|
||
|
* to grow the heap. If the heap is full and is already at maximum
|
||
|
* size, no blocking will be performed.
|
||
|
*
|
||
|
* \note This function may block.
|
||
|
*
|
||
|
* \param[in] _heap Heap to allocate from.
|
||
|
* \param[in] _size Number of bytes to allocate.
|
||
|
* \param[in] _alignment Number of bytes the allocation should be
|
||
|
* aligned on.
|
||
|
* \param[in] _timeoutMS Maximum wait time in milliseconds.
|
||
|
*
|
||
|
* \retval NULL Cannot allocate 'size' bytes from specified heap.
|
||
|
* \return Address of allocated memory of the specified size.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
#define vmk_HeapAlignWithTimeout(_heap, _size, _alignment, _timeoutMS) \
|
||
|
(vmk_HeapAlignWithTimeoutAndRA((_heap), (_size), (_alignment), \
|
||
|
(_timeoutMS), __builtin_return_address(0)))
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapGetProperties -- */ /**
|
||
|
*
|
||
|
* \brief Get the properties of the heap
|
||
|
*
|
||
|
* \note The properties returned may not necessarily be the same as
|
||
|
* those specified when the heap was created. Some properties are
|
||
|
* adjusted by the heap internal implementation to conform to
|
||
|
* implementation details. For example, a heap maximum size may
|
||
|
* be rounded up due to alignment of allocations. The values
|
||
|
* returned are those that are actually used by the heap.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] heap Heap that caller is interogating.
|
||
|
* \param[out] props The heap's properties.
|
||
|
*
|
||
|
* \retval VMK_OK Properties successfully retrieved.
|
||
|
* \retval VMK_BAD_PARAM heap was not a valid heap ID.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
VMK_ReturnStatus
|
||
|
vmk_HeapGetProperties(vmk_HeapID heap, vmk_HeapGetProps *props);
|
||
|
|
||
|
/*
|
||
|
***********************************************************************
|
||
|
* vmk_HeapDetermineMaxSize -- */ /**
|
||
|
*
|
||
|
* \brief Determines the required maximum size of a heap in bytes.
|
||
|
*
|
||
|
* Determines the required maximum size of a heap that will contain
|
||
|
* the descriptors described in the descriptors array. Note that this
|
||
|
* does not include overhead for fragmentation within the heap and it
|
||
|
* is the caller's responsibility to add that in when creating the heap.
|
||
|
*
|
||
|
* \note This function will not block.
|
||
|
*
|
||
|
* \param[in] descriptors Pointer to an array of descriptors that
|
||
|
* the heap will contain. An alignment of
|
||
|
* zero for a descriptor indicates no
|
||
|
* alignment is specified by the caller and
|
||
|
* the heap code will use a value it
|
||
|
* determines.
|
||
|
* \param[in] numDescriptors Number of vmk_HeapAllocationDescriptors
|
||
|
* in the array pointed to by descriptors.
|
||
|
* \param[out] maxSize The determined maximum size.
|
||
|
*
|
||
|
* \retval VMK_OK Size determined successfully and placed
|
||
|
* in maxSize.
|
||
|
* \retval VMK_BAD_PARAM One of the arguments is invalid, or one
|
||
|
* of the descriptors contains an invalid
|
||
|
* value.
|
||
|
* \retval VMK_LIMIT_EXCEEDED The total size required for the
|
||
|
* provided descriptors results in a heap
|
||
|
* greater than the largest possible
|
||
|
* allowed.
|
||
|
*
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
VMK_ReturnStatus
|
||
|
vmk_HeapDetermineMaxSize(vmk_HeapAllocationDescriptor *descriptors,
|
||
|
vmk_uint64 numDescriptors,
|
||
|
vmk_ByteCount *maxSize);
|
||
|
|
||
|
#endif /* _VMKAPI_HEAP_H_ */
|
||
|
/** @} */
|
||
|
/** @} */
|