vmkdrivers/BLD/build/HEADERS/vmkapi-current/vmkernel64/release/base/vmkapi_slab.h
2015-10-23 15:21:55 -04:00

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_ */
/** @} */