| |
| |
| |
| |
| |
| |
|
|
| #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); |
| } |
|
|
| } |
| } |
|
|
|
|