Files
handleaiuinew/env/LMI/include/kApi/Utils/kPoolAlloc.x.h
T
2024-05-18 23:53:26 +08:00

210 lines
12 KiB
C

/**
* @file kPoolAlloc.x.h
*
* @internal
* Copyright (C) 2013-2021 by LMI Technologies Inc. All rights reserved.
*/
#ifndef K_API_POOL_ALLOC_X_H
#define K_API_POOL_ALLOC_X_H
#define xkPOOL_ALLOC_DEFAULT_BLOCK_SIZE (1 << 14) ///< Default value for BlockSize property, in bytes.
#define xkPOOL_ALLOC_DEFAULT_MAX_BLOCK_BUFFER_SIZE (0) ///< Default value for MaxBlockBufferSize property, in bytes.
#define xkPOOL_ALLOC_DEFAULT_BLOCK_CAPACITY (kSIZE_MAX) ///< Default value for BlockCapacity property, in bytes.
#define xkPOOL_ALLOC_DEFAULT_BLOCK_REUSE_ENABLED (kTRUE) ///< Default value for BlockReuseEnabled property.
#define xkPOOL_ALLOC_DEFAULT_MAX_CACHED_BUFFER_SIZE (0) ///< Default value for MaxCachedBufferSize property, in bytes.
#define xkPOOL_ALLOC_DEFAULT_CACHE_CAPACITY (kSIZE_MAX) ///< Default value for CacheCapacity property, in bytes.
#define xkPOOL_ALLOC_DEFAULT_TOTAL_CAPACITY (kSIZE_MAX) ///< Default value for TotalCapacity property, in bytes.
#define xkPOOL_ALLOC_RANK_CAPACITY (32) ///< kPoolAlloc can optimize 32-bit or smaller allocations (limited by use of kMath_Log2Ceil32u to compute rank).
#define xkPOOL_ALLOC_MAX_MANAGED_BUFFER_SIZE (0x80000000) ///< Based on xkPOOL_ALLOC_RANK_CAPACITY, hard interal limit on optimized buffer size.
#define xkPOOL_ALLOC_MIN_HEADERS_PER_BLOCK (8) ///< Used in block allocation to ensure at least N buffer headers will fit (helps reduce fragementation).
#define xkPOOL_ALLOC_ALLOC_TYPE_MASK (1) ///< Used to distinguish between type (bit set) and aligned address (bit clear)
/**
* @internal
* @struct xkPoolAllocAllocType
* @ingroup kApi-Utils
* @brief Represents a kPoolAlloc allocation type GUID.
*
* Allocation type identifiers are dynamically-generated GUIDs (use of GUIDs improves ability to detect
* invalid deallocations). Must have xkPOOL_ALLOC_BUFFER_HEADER_TYPE_MASK bit set.
*/
typedef kSize xkPoolAllocAllocType;
/**
* @internal
* @struct xkPoolAllocBlockHeader
* @ingroup kApi-Utils
* @brief Header for a kPoolAlloc buffer allocation block.
*/
typedef struct xkPoolAllocBlockHeader
{
kSize allocCount; ///< Count of allocations made from this block.
kSize refCount; ///< Count of allocations from this block that are currently in use (not free).
kSize rank; ///< Base-2 logarithm of block buffer size (index into kPoolAlloc rank array; kSIZE_NULL if block unassigned).
struct xkPoolAllocBlockHeader* next; ///< Pointer to next block (used in xkPoolAllocRank.newBlockList, xkPoolAllocRank.freeBlockList, kPoolAlloc.unassignedBlockList).
struct xkPoolAllocBlockHeader* previous; ///< Pointer to previous block (used in xkPoolAllocRank.newBlockList, xkPoolAllocRank.freeBlockList, kPoolAlloc.unassignedBlockList).
kSize unused; ///< Structure allocation padding.
} xkPoolAllocBlockHeader;
/**
* @internal
* @struct xkPoolAllocBufferHeader
* @ingroup kApi-Utils
* @brief Header for a kPoolAlloc memory buffer.
*/
typedef struct xkPoolAllocBufferHeader
{
union
{
xkPoolAllocBlockHeader* block; ///< For block-based allocations, the block from which this allocation was created.
kSize rank; ///< For potentially-cached allocations, the rank associated with the allocation.
kSize size; ///< For unmanaged allocations, the raw size of the allocation (excluding header).
} info; ///< Allocation-type-specific information.
struct xkPoolAllocBufferHeader* next; ///< Pointer to next buffer (used in xkPoolAllocRank.freeBufferList).
struct xkPoolAllocBufferHeader* previous; ///< Pointer to previous buffer (used in xkPoolAllocRank.freeBufferList).
xkPoolAllocAllocType type; ///< Type of kPoolAlloc allocation.
} xkPoolAllocBufferHeader;
/**
* @internal
* @struct xkPoolAllocBlockList
* @ingroup kApi-Utils
* @brief List of kPoolAlloc memory blocks.
*/
typedef struct xkPoolAllocBlockList
{
xkPoolAllocBlockHeader* first; ///< Head of block list.
xkPoolAllocBlockHeader* last; ///< Tail of block list.
kSize count; ///< Count of items in block list.
} xkPoolAllocBlockList;
/**
* @internal
* @struct xkPoolAllocBufferList
* @ingroup kApi-Utils
* @brief List of kPoolAlloc memory buffers.
*/
typedef struct xkPoolAllocBufferList
{
xkPoolAllocBufferHeader* first; ///< Head of buffer list.
xkPoolAllocBufferHeader* last; ///< Tail of buffer list.
kSize count; ///< Count of items in buffer list.
} xkPoolAllocBufferList;
/**
* @internal
* @struct xkPoolAllocRank
* @ingroup kApi-Utils
* @brief Represents kPoolAlloc information related to a specific memory rank.
*/
typedef struct xkPoolAllocRank
{
kSize rank; ///< Rank (base-2 logarithm of buffer size).
kSize size; ///< Size of buffer associate with this rank.
kSize bufferStride; ///< Memory footprint of one block-based buffer, including buffer header and alignment padding.
kBool isBlockBased; ///< Use blocks to allocate buffers?
kBool isCached; ///< Cache deallocated buffers for later use?
kSize buffersPerBlock; ///< Count of buffers that can be allocated per block.
kSize bufferCount; ///< Count of buffers in use for this rank (allocated or cached).
kSize minBufferCount; ///< Count of buffers reserved for this rank.
xkPoolAllocBufferList freeBufferList; ///< List of free buffers.
xkPoolAllocBlockList newBlockList; ///< List of blocks whose allocCount is less than buffersPerBlock.
xkPoolAllocBlockList freeBlockList; ///< List of blocks with a reference count of zero (not currently in use).
} xkPoolAllocRank;
typedef struct kPoolAllocClass
{
kAllocClass base;
kLock lock; //Provides mutual exclusion.
kBool inheritPriority; //Support priority inheritance?
kSize nominalBlockSize; //Nominal block size for block-based allocations (exluding header), in bytes.
kSize maxBlockBufferSize; //Maximum buffer size for an individual block-based allocation, in bytes.
kSize blockCapacity; //Maximum memory used to allocate blocks, in bytes.
kBool blockReuseEnabled; //Can blocks be automatically reassigned between ranks as needed?
kSize maxCachedBufferSize; //Maximum buffer size for an individual cached allocation, in bytes.
kSize cacheCapacity; //Maximum amount of non-block memory to retain upon deallocation, in bytes.
kSize totalCapacity; //Maximum amount of memory that can be requested from underlying allocator.
kSize blockBasedRankCount; //Count of ranks potentially eligible for block-based allocation.
kSize cacheBasedRankCount; //Count of ranks potentially eligible for cache-based allocation.
kSize managedRankCount; //Maximum of blockBasedRankCount and cacheBasedRankCount.
kSize maxManagedBufferSize; //Maximum size of managed buffer.
kSize blockAllocId; //GUID for block allocations from this allocator.
kSize cacheAllocId; //GUID for cached allocations from this allocator.
kSize unmanagedAllocId; //GUID for unmanaged allocations from this allocator.
kBool isStarted; //Has pool-alloc been started?
xkPoolAllocRank rankInfo[xkPOOL_ALLOC_RANK_CAPACITY]; //Information associated with each rank.
xkPoolAllocBlockList unassignedBlockList; //List of blocks blocks not yet assigned to any rank.
kSize blockCount; //Total number of blocks currently allocated from underlying allocator.
kSize minBlockCount; //Minimum number of blocks that should be allocated from underlying allocator (reservation).
kSize cacheSize; //Total size of free, cached (non-block) allocations, excluding headers, in bytes.
kSize totalSize; //Total amount of memory currently drawn from underlying allocator.
} kPoolAllocClass;
kDeclareClassEx(k, kPoolAlloc, kAlloc)
/*
* Private methods.
*/
kFx(kStatus) xkPoolAlloc_Init(kPoolAlloc object, kType type, kAlloc alloc);
kFx(kStatus) xkPoolAlloc_VRelease(kPoolAlloc object);
kFx(kStatus) xkPoolAlloc_VGet(kPoolAlloc object, kSize size, void* mem, kMemoryAlignment alignment);
kFx(kStatus) xkPoolAlloc_VFree(kPoolAlloc object, void* mem);
kFx(kStatus) xkPoolAlloc_EnablePriorityInheritance(kPoolAlloc object, kBool enable);
kFx(kStatus) xkPoolAlloc_ReserveBlocksAt(kPoolAlloc object, kSize rank, kSize size);
kFx(kStatus) xkPoolAlloc_ReserveCachedBuffersAt(kPoolAlloc object, kSize rank, kSize size);
kFx(void) xkPoolAlloc_RemoveFromBlockList(kPoolAlloc object, xkPoolAllocBlockList* list, xkPoolAllocBlockHeader* item);
kFx(void) xkPoolAlloc_InsertIntoBlockList(kPoolAlloc object, xkPoolAllocBlockList* list, xkPoolAllocBlockHeader* before, xkPoolAllocBlockHeader* item);
kFx(void) xkPoolAlloc_RemoveFromBufferList(kPoolAlloc object, xkPoolAllocBufferList* list, xkPoolAllocBufferHeader* item);
kFx(void) xkPoolAlloc_InsertIntoBufferList(kPoolAlloc object, xkPoolAllocBufferList* list, xkPoolAllocBufferHeader* before, xkPoolAllocBufferHeader* item);
kFx(kStatus) xkPoolAlloc_AddBlockRef(kPoolAlloc object, xkPoolAllocBlockHeader* block);
kFx(kStatus) xkPoolAlloc_RemoveBlockRef(kPoolAlloc object, xkPoolAllocBlockHeader* block);
kFx(kStatus) xkPoolAlloc_AllocBlock(kPoolAlloc object);
kFx(kStatus) xkPoolAlloc_AllocCachedBuffers(kPoolAlloc object, kSize rank, kSize count);
kFx(kStatus) xkPoolAlloc_AllocUnmanagedBuffer(kPoolAlloc object, kSize size, void* mem, kMemoryAlignment alignment);
kFx(kStatus) xkPoolAlloc_PrepareFreeBlockBasedBuffer(kPoolAlloc object, kSize rank);
kFx(kStatus) xkPoolAlloc_RecycleBlocks(kPoolAlloc object, kSize maxCount);
kFx(kStatus) xkPoolAlloc_ReturnBlockToUnassigned(kPoolAlloc object, xkPoolAllocBlockList* list, xkPoolAllocBlockHeader* block);
kFx(kStatus) xkPoolAlloc_ClearEx(kPoolAlloc object, kBool all);
kFx(kStatus) xkPoolAlloc_FreeUnassignedBlocks(kPoolAlloc object);
kFx(kStatus) xkPoolAlloc_FreeCachedBuffers(kPoolAlloc object);
/** Reports size of a single block, excluding block header, in bytes. */
kInlineFx(kSize) xkPoolAlloc_BlockContentSize(kPoolAlloc object)
{
kObj(kPoolAlloc, object);
return obj->nominalBlockSize + xkPOOL_ALLOC_MIN_HEADERS_PER_BLOCK*sizeof(xkPoolAllocBufferHeader) + kALIGN_ANY_SIZE;
}
kInlineFx(kSize) xkPoolAlloc_AllocBlockSize(kPoolAlloc object)
{
kObj(kPoolAlloc, object);
return sizeof(xkPoolAllocBlockHeader) + xkPoolAlloc_BlockContentSize(object);
}
#endif