388 lines
14 KiB
C
388 lines
14 KiB
C
/* **********************************************************
|
|
* Copyright 1998 - 2009 VMware, Inc. All rights reserved.
|
|
* **********************************************************/
|
|
|
|
/*
|
|
* @VMKAPIMOD_LICENSE@
|
|
*/
|
|
|
|
/*
|
|
***********************************************************************
|
|
* Slabs */ /**
|
|
* \defgroup Slab Slab Allocation
|
|
*
|
|
* ESX Server supports slab allocation for high performance driver/stack
|
|
* implementations:
|
|
* - Reduces memory fragmentation, especially for smaller data structures
|
|
* allocated in high volume.
|
|
* - Reduces CPU consumption for data structure initialization/teardown.
|
|
* - Improves CPU hardware cache performance.
|
|
* - Provides finer grained control of memory consumption.
|
|
* - Builds structure upon the VMKAPI heap layer.
|
|
*
|
|
* The ESX concept of slab is a bit different from several well known
|
|
* OS implemenations, in that ESX slabs are not physically contiguous
|
|
* chunks of memory. An ESX slab is in fact a collection of free
|
|
* objects (as seen by the slab user). As seen by the heap, these
|
|
* objects appear allocated.
|
|
*
|
|
*@{
|
|
*
|
|
* \par Slab Layout Considerations
|
|
*
|
|
* Care must be taken when designing a slab to ensure that the layout can
|
|
* actually be constructed. The following properties (see
|
|
* \b vmk_SlabProps structure) are particularly critical.
|
|
*
|
|
* - \b maxTotalObj
|
|
* \n
|
|
* Specifies the maximum number of objects that can be in the slab, including
|
|
* free objects cached by the slab, plus objects allocated by the user.
|
|
* Slab creation will fail if the specified objects, including internal slab
|
|
* overheads, cannot be accommodated in the portion of the heap available to
|
|
* the slab (see \b slabPercent below).
|
|
* \note
|
|
* Also note that object size may be rounded up to satisfy \b props->alignment.
|
|
*
|
|
* - \b maxFreeObj:
|
|
* \n
|
|
* In the \b VMK_SLAB_TYPE_SIMPLE, specifies the maximum number of free
|
|
* objects that may reside in the slab. In the \b VMK_SLAB_TYPE_NOMINAL
|
|
* case, specifies the maximum number of free objects that can be immediately
|
|
* allocated from the per-physical CPU caches (a portion of the slab).
|
|
* In the NOMINAL case, the maximum number of free objects is constrained
|
|
* by \b slabPercent.
|
|
* \note
|
|
* In the \b VMK_SLAB_TYPE_SIMPLE case, a heuristic typically
|
|
* sets a lower constraint on the PCPU cache size. Use
|
|
* \b VMK_SLAB_TYPE_NOMINAL if you need more precise control.
|
|
* \note
|
|
* Even then, further adjustments may be made during slab creation,
|
|
* so that the per-PCPU cache size falls into a range that internal
|
|
* data structures can efficiently handle.
|
|
*
|
|
* - \b slabPercent:
|
|
* \n
|
|
* For the \b VMK_SLAB_TYPE_SIMPLE case, gives the percentage of the heap
|
|
* that can be utilized by free objects in the slab.
|
|
*
|
|
* - \b ctrlOffset:
|
|
* \n
|
|
* Allows the developer to overlay slab control information (used
|
|
* only for free objects) with the object space (thus saving space)
|
|
* See \b vmk_SlabControlSize for more information.
|
|
*
|
|
* - \b notrim:
|
|
* \n
|
|
* If set, specifies that the slab will never free objects
|
|
* back to underlying heap. If this flag is set, then \b slabPercent
|
|
* must be 100.
|
|
*
|
|
* \note
|
|
* It should be clear that excessively large values for maxTotalObj or
|
|
* maxFreeObj, or alternatively, a small value for slabPercent,
|
|
* can cause slab creation to fail if the portion of the heap made available
|
|
* cannot accomodate the number of obects specified (including overheads).
|
|
* \note
|
|
* A similar problem may arise if maxTotalObj cannot accomodate
|
|
* maxFreeObj after the latter has been adjusted (up or down) by internal
|
|
* considerations. Since esx4.1 can support upto 256 physical CPU cores,
|
|
* maxTotalObj should be set to a minimum of 1024.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
|
|
#ifndef _VMKAPI_SLAB_H_
|
|
#define _VMKAPI_SLAB_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 */
|
|
|
|
#include "base/vmkapi_types.h"
|
|
#include "base/vmkapi_const.h"
|
|
#include "base/vmkapi_heap.h"
|
|
#include "base/vmkapi_status.h"
|
|
|
|
|
|
/**
|
|
* \ingroup Slab
|
|
* \brief Opaque handle for a slab cache
|
|
*/
|
|
typedef struct vmk_SlabIDInt *vmk_SlabID;
|
|
|
|
#define VMK_INVALID_SLAB_ID ((vmk_SlabID)NULL)
|
|
|
|
/* Max length of a slab name, including the trailing NUL character */
|
|
#define VMK_MAX_SLAB_NAME 32
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabItemConstructor -- */ /**
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Item constructor - optional user defined function. Runs for
|
|
* each object when a cluster of memory is
|
|
* allocated from the heap.
|
|
*
|
|
* \note When the control structure is placed inside the free object,
|
|
* then the constructor must take care not to modify the control
|
|
* structure.
|
|
*
|
|
* \param[in] object Object to be constructed.
|
|
* \param[in] size Size of buffer (possibly greater than objSize).
|
|
* \param[in] arg constructorArg (see vmk_SlabProps).
|
|
* \param[in] flags Currently unused (reserved for future use).
|
|
*
|
|
* \retval VMK_OK to indicate object construction has succeded.
|
|
* \return Other To indicate failure.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
typedef VMK_ReturnStatus (*vmk_SlabItemConstructor)(void *object,
|
|
vmk_small_size_t size,
|
|
vmk_AddrCookie arg,
|
|
int flags);
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabItemDestructor -- */ /**
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Item destructor - optional user defined function. Runs for
|
|
* each buffer just before a cluster of memory
|
|
* is returned to the heap.
|
|
*
|
|
* \note When the control structure is placed inside the free object,
|
|
* then the destructor must take care not to modify the control
|
|
* structure.
|
|
*
|
|
* \param[in] object Object to be destroyed.
|
|
* \param[in] size Size of buffer (possibly greater than objSize).
|
|
* \param[in] arg constructorArg (see vmk_SlabProps).
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
typedef void (*vmk_SlabItemDestructor)(void *object, vmk_small_size_t size,
|
|
vmk_AddrCookie arg);
|
|
|
|
/**
|
|
* \ingroup Slab
|
|
* \brief Types of slab
|
|
*/
|
|
typedef enum {
|
|
VMK_SLAB_TYPE_SIMPLE=0,
|
|
VMK_SLAB_TYPE_NOMINAL=1
|
|
} vmk_SlabType;
|
|
|
|
/**
|
|
* \ingroup Slab
|
|
* \brief Properties of a slab allocator
|
|
*/
|
|
typedef struct {
|
|
/** \brief Type of slab */
|
|
vmk_SlabType type;
|
|
|
|
/** \brief Byte Size of each object */
|
|
vmk_small_size_t objSize;
|
|
|
|
/** \brief Byte alignment for each object */
|
|
vmk_small_size_t alignment;
|
|
|
|
/** \brief Called after an object is allocated (or NULL for no action) */
|
|
vmk_SlabItemConstructor constructor;
|
|
|
|
/** \brief Called before an object is freed (or NULL for no action) */
|
|
vmk_SlabItemDestructor destructor;
|
|
|
|
/** \brief Arument for constructor/destructor calls */
|
|
vmk_AddrCookie constructorArg;
|
|
|
|
/** \brief Type-specific slab properties */
|
|
union {
|
|
/** \brief Properties for VMK_SLAB_TYPE_SIMPLE, */
|
|
struct {
|
|
/*
|
|
* \brief Backing store for the cache clusters.
|
|
*
|
|
* This value must be a valid heap ID previously constructed by
|
|
* vmk_HeapCreate or vmk_HeapCreatePkeVisible. It may not be
|
|
* VMK_INVALID_HEAP_ID.
|
|
*/
|
|
vmk_HeapID heap;
|
|
|
|
/** \brief Max total objects. */
|
|
vmk_uint32 maxTotalObj;
|
|
|
|
/** \brief Max free objects (across all PCPUs). */
|
|
vmk_uint32 maxFreeObj;
|
|
} simple;
|
|
|
|
/*
|
|
* \brief Properties for VMK_SLAB_TYPE_NOMINAL
|
|
*
|
|
* Use VMK_SLAB_TYPE_NOMINAL for finer control of slab
|
|
* properties.
|
|
*/
|
|
struct {
|
|
/*
|
|
* \brief Backing store for the cache clusters.
|
|
*
|
|
* This value must be a valid heap ID previously constructed by
|
|
* vmk_HeapCreate or vmk_HeapCreatePkeVisible. It may not be
|
|
* VMK_INVALID_HEAP_ID.
|
|
*/
|
|
vmk_HeapID heap;
|
|
|
|
/** \brief Max total objects */
|
|
vmk_uint32 maxTotalObj;
|
|
|
|
/** \brief Max free objects in all PCPU caches */
|
|
vmk_uint32 maxFreeObj;
|
|
|
|
/** \brief Cap on percentage of the heap consumed by the slab */
|
|
vmk_uint32 slabPercent;
|
|
|
|
/** \brief See vmk_SlabControlSize */
|
|
vmk_small_size_t ctrlOffset;
|
|
|
|
/**
|
|
* \brief Don't free to the backing heap until
|
|
* vmk_SlabDestroy is called.
|
|
*/
|
|
unsigned notrim:1;
|
|
} nominal;
|
|
} typeSpecific;
|
|
} vmk_SlabProps;
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabCreate -- */ /**
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Create a slab allocator cache.
|
|
*
|
|
* \param [in] name Name associated with the new cache.
|
|
* \param [in] props Properties of the new cache.
|
|
* \param [out] cache For use with vmk_SlabAlloc, etc.
|
|
*
|
|
* \retval VMK_OK To indicate that slab creation has succeeded.
|
|
* \retval VMK_BAD_PARAM Either \em props is NULL or \em props->type
|
|
* is invalid.
|
|
* \retval VMK_FAILURE \em heap (a field within the \em props union)
|
|
* does not specify a valid \em vmk_HeapID.
|
|
* \retval VMK_LIMIT_EXCEEDED The underlying heap is too small to contain
|
|
* \em maxTotalObjects.
|
|
* (a field within the \em props union).
|
|
* \retval VMK_FAILURE \em ctrlOffset (a field within the \em props union)
|
|
* is larger than the object size.
|
|
* \retval VMK_FAILURE \em slabPercent (a field within the \em props union)
|
|
* is either negative or larger than 100.
|
|
* \retval VMK_FAILURE \em props specifies an inconsistent layout.
|
|
*
|
|
* \note For debug builds (beta and obj vmkernel types) VMK_FAILURE will
|
|
* not be returned if an inconsistent layout is detected. Instead an
|
|
* assert will trip resulting in a \b NOT_REACHED PSOD. A message
|
|
* similar to the following is logged immediately preceeding the PSOD:
|
|
* \code
|
|
* Slab: Layout:692: Layout undoable: slabBytes 112, oneCacheBytes 58, \
|
|
* clusterBytes 29, freeClusterLength 1, clusterSize 0
|
|
* \endcode
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
VMK_ReturnStatus vmk_SlabCreate(const char *name,
|
|
vmk_SlabProps *props,
|
|
vmk_SlabID *cache);
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabAlloc --
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Allocate an item from a slab.
|
|
*
|
|
* The vmk_SlabItemConstructor (if defined) was previously called,
|
|
* or the object was previously freed via vmk_SlabFree().
|
|
*
|
|
* \note When the control structure is placed inside the free object,
|
|
* the caller of vmk_SlabAlloc() must assume this portion of
|
|
* the object is uninitialized.
|
|
*
|
|
* \param[in] cache Slab from which allocation will take place.
|
|
*
|
|
* \retval NULL Memory could not be allocated.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void *vmk_SlabAlloc(vmk_SlabID cache);
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabFree --
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Free memory allocated by vmk_SlabAlloc.
|
|
*
|
|
* The memory object will be retained by the slab. If at
|
|
* some point the slab chooses to give the memory back to the
|
|
* system, the vmk_SlabItemDestructor (if defined) will be called.
|
|
*
|
|
* \param[in] cache Slab from which the item was allocated.
|
|
* \param[in] object object to be freed.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
void vmk_SlabFree(
|
|
vmk_SlabID cache,
|
|
void *item);
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabDestroy --
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Tear down a slab cache allocated previously created by
|
|
* vmk_SlabCreate.
|
|
*
|
|
* \param[in] cache The cache to be destroyed.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
VMK_ReturnStatus vmk_SlabDestroy(vmk_SlabID cache);
|
|
|
|
|
|
/*
|
|
***********************************************************************
|
|
* vmk_SlabControlSize --
|
|
*
|
|
* \ingroup Slab
|
|
* \brief Get the size of the per-object "control" structure.
|
|
*
|
|
* The slab maintains a control structure for each free object
|
|
* cached by the slab. When VMK_SLAB_TYPE_SIMPLE properties are
|
|
* used to create the slab, the control structure will be tacked
|
|
* past the end of the client's object. To save space, the control
|
|
* structure can be placed within the user's free object using the
|
|
* ctrlOffset paramter to VMK_SLAB_TYPE_NOMINAL properties.
|
|
*
|
|
* \note See vmk_SlabItemConstructor, vmk_SlabItemDestructor and
|
|
* and vmk_SlabAlloc for the constraints that must be obeyed
|
|
* when the control structure is placed inside the object.
|
|
*
|
|
* \return Size of the control structure in bytes.
|
|
*
|
|
***********************************************************************
|
|
*/
|
|
vmk_small_size_t vmk_SlabControlSize(void);
|
|
|
|
#endif /* _VMKAPI_SLAB_H_ */
|
|
/** @} */
|