|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "NvCoFreeList.h" |
|
|
|
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
#define DEFAULT_ALIGNMENT 16 |
|
|
|
|
|
namespace nvidia { |
|
|
namespace Common { |
|
|
|
|
|
FreeList::~FreeList() |
|
|
{ |
|
|
_deallocateBlocks(m_activeBlocks); |
|
|
_deallocateBlocks(m_freeBlocks); |
|
|
} |
|
|
|
|
|
void FreeList::_init() |
|
|
{ |
|
|
m_top = nullptr; |
|
|
m_end = nullptr; |
|
|
|
|
|
m_activeBlocks = nullptr; |
|
|
m_freeBlocks = nullptr; |
|
|
|
|
|
m_freeElements = nullptr; |
|
|
|
|
|
m_elementSize = 0; |
|
|
m_alignment = 1; |
|
|
m_blockSize = 0; |
|
|
m_blockAllocationSize = 0; |
|
|
|
|
|
} |
|
|
|
|
|
void FreeList::_init(size_t elementSize, size_t alignment, size_t elemsPerBlock) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
alignment = (alignment < sizeof(void*)) ? sizeof(void*) : alignment; |
|
|
|
|
|
|
|
|
assert(((alignment - 1) & alignment) == 0); |
|
|
|
|
|
|
|
|
elementSize = (elementSize >= alignment) ? elementSize : alignment; |
|
|
m_blockSize = elementSize * elemsPerBlock; |
|
|
m_elementSize = elementSize; |
|
|
m_alignment = alignment; |
|
|
|
|
|
|
|
|
const size_t alignedBlockSize = (alignment <= DEFAULT_ALIGNMENT) ? |
|
|
_calcAlignedBlockSize(DEFAULT_ALIGNMENT) : |
|
|
_calcAlignedBlockSize(alignment); |
|
|
|
|
|
|
|
|
m_blockAllocationSize = m_blockSize + alignedBlockSize; |
|
|
|
|
|
m_top = nullptr; |
|
|
m_end = nullptr; |
|
|
|
|
|
m_activeBlocks = nullptr; |
|
|
m_freeBlocks = nullptr; |
|
|
|
|
|
m_freeElements = nullptr; |
|
|
} |
|
|
|
|
|
void FreeList::init(size_t elementSize, size_t alignment, size_t elemsPerBlock) |
|
|
{ |
|
|
_deallocateBlocks(m_activeBlocks); |
|
|
_deallocateBlocks(m_freeBlocks); |
|
|
_init(elementSize, alignment, elemsPerBlock); |
|
|
} |
|
|
|
|
|
void FreeList::_deallocateBlocks(Block* block) |
|
|
{ |
|
|
while (block) |
|
|
{ |
|
|
Block* next = block->m_next; |
|
|
|
|
|
#ifdef NV_CO_FREE_LIST_INIT_MEM |
|
|
Memory::set(block, 0xfd, m_blockAllocationSize); |
|
|
#endif |
|
|
|
|
|
free(block); |
|
|
block = next; |
|
|
} |
|
|
} |
|
|
|
|
|
bool FreeList::isValidAllocation(const void* dataIn) const |
|
|
{ |
|
|
uint8_t* data = (uint8_t*)dataIn; |
|
|
|
|
|
Block* block = m_activeBlocks; |
|
|
while (block) |
|
|
{ |
|
|
uint8_t* start = block->m_data; |
|
|
uint8_t* end = start + m_blockSize; |
|
|
|
|
|
if (data >= start && data < end) |
|
|
{ |
|
|
|
|
|
if ((data - start) % m_elementSize) |
|
|
{ |
|
|
return false; |
|
|
} |
|
|
|
|
|
|
|
|
if (data >= m_top && data < m_end) |
|
|
{ |
|
|
return false; |
|
|
} |
|
|
|
|
|
|
|
|
Element* ele = m_freeElements; |
|
|
while (ele) |
|
|
{ |
|
|
if (ele == (Element*)data) |
|
|
{ |
|
|
return false; |
|
|
} |
|
|
|
|
|
ele = ele->m_next; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
block = block->m_next; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
void* FreeList::_allocate() |
|
|
{ |
|
|
Block* block = m_freeBlocks; |
|
|
if (block) |
|
|
{ |
|
|
|
|
|
m_freeBlocks = block->m_next; |
|
|
} |
|
|
else |
|
|
{ |
|
|
block = (Block*)malloc(m_blockAllocationSize); |
|
|
if (!block) |
|
|
{ |
|
|
|
|
|
return nullptr; |
|
|
} |
|
|
|
|
|
{ |
|
|
size_t fix = (size_t(block) + sizeof(Block) + m_alignment - 1) & ~(m_alignment - 1); |
|
|
block->m_data = (uint8_t*)fix; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
block->m_next = m_activeBlocks; |
|
|
m_activeBlocks = block; |
|
|
|
|
|
|
|
|
m_end = block->m_data + m_blockSize; |
|
|
|
|
|
|
|
|
uint8_t* element = block->m_data; |
|
|
m_top = element + m_elementSize; |
|
|
|
|
|
NV_CO_FREE_LIST_INIT_ALLOCATE(element) |
|
|
|
|
|
return element; |
|
|
} |
|
|
|
|
|
void FreeList::deallocateAll() |
|
|
{ |
|
|
Block* block = m_activeBlocks; |
|
|
if (block) |
|
|
{ |
|
|
|
|
|
while (block->m_next) |
|
|
{ |
|
|
#ifdef NV_CO_FREE_LIST_INIT_MEM |
|
|
Memory::set(block->m_data, 0xfd, m_blockSize); |
|
|
#endif |
|
|
block = block->m_next; |
|
|
} |
|
|
|
|
|
block->m_next = m_freeBlocks; |
|
|
|
|
|
m_freeBlocks = m_activeBlocks; |
|
|
|
|
|
m_activeBlocks = nullptr; |
|
|
} |
|
|
|
|
|
m_top = nullptr; |
|
|
m_end = nullptr; |
|
|
} |
|
|
|
|
|
void FreeList::reset() |
|
|
{ |
|
|
_deallocateBlocks(m_activeBlocks); |
|
|
_deallocateBlocks(m_freeBlocks); |
|
|
|
|
|
m_top = nullptr; |
|
|
m_end = nullptr; |
|
|
|
|
|
m_activeBlocks = nullptr; |
|
|
m_freeBlocks = nullptr; |
|
|
|
|
|
m_freeElements = nullptr; |
|
|
} |
|
|
|
|
|
|
|
|
void FreeList::_initAllocate(void* mem) |
|
|
{ |
|
|
memset(mem, 0xcd, m_elementSize); |
|
|
} |
|
|
|
|
|
void FreeList::_initDeallocate(void* mem) |
|
|
{ |
|
|
memset(mem, 0xfd, m_elementSize); |
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|