#include "GpAllocator_C.h" #include "CoreDefs.h" #include #include #include struct GpAllocator_C_MMBlock { uint8_t m_offsetFromAllocLocation; static size_t AlignedSize(); }; size_t GpAllocator_C_MMBlock::AlignedSize() { const size_t paddedSize = sizeof(GpAllocator_C_MMBlock) + GP_SYSTEM_MEMORY_ALIGNMENT - 1; const size_t paddedSizeTruncated = paddedSize - (paddedSize % GP_SYSTEM_MEMORY_ALIGNMENT); return paddedSizeTruncated; } void *GpAllocator_C::Realloc(void *buf, size_t newSize) { if (buf == nullptr) { if (newSize == 0) return nullptr; return this->Alloc(newSize); } if (newSize == 0) { this->Free(buf); return nullptr; } assert(buf != nullptr); const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize(); uint8_t *oldBufBytes = static_cast(buf); const GpAllocator_C_MMBlock *oldBufMMBlock = reinterpret_cast(oldBufBytes - GpAllocator_C_MMBlock::AlignedSize()); const size_t oldBufOffsetFromAlignLoc = oldBufMMBlock->m_offsetFromAllocLocation; uint8_t *oldBufBase = oldBufBytes - GpAllocator_C_MMBlock::AlignedSize() - oldBufOffsetFromAlignLoc; const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; if (SIZE_MAX - newSize < mmBlockSizeWithMaxPadding) return nullptr; const size_t newBufferSize = newSize + mmBlockSizeWithMaxPadding; uint8_t *newBuffer = static_cast(realloc(oldBufBase, newSize + mmBlockSizeWithMaxPadding)); if (!newBuffer) return nullptr; const intptr_t offsetFromAlignPoint = reinterpret_cast(newBuffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); intptr_t alignPadding = 0; if (offsetFromAlignPoint != 0) alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; // Check if the alignment changed, if so relocate if (static_cast(alignPadding) != oldBufOffsetFromAlignLoc) memmove(newBuffer + alignPadding, newBuffer + oldBufOffsetFromAlignLoc, GpAllocator_C_MMBlock::AlignedSize() + newSize); GpAllocator_C_MMBlock *newMMBlock = reinterpret_cast(newBuffer + alignPadding); newMMBlock->m_offsetFromAllocLocation = static_cast(alignPadding); return newBuffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize(); } void *GpAllocator_C::Alloc(size_t size) { if (size == 0) return nullptr; const size_t mmBlockSizeWithMaxPadding = GpAllocator_C_MMBlock::AlignedSize() + GP_SYSTEM_MEMORY_ALIGNMENT - 1; if (SIZE_MAX - size < mmBlockSizeWithMaxPadding) return nullptr; uint8_t *buffer = static_cast(realloc(nullptr, size + mmBlockSizeWithMaxPadding)); if (!buffer) return nullptr; const intptr_t offsetFromAlignPoint = reinterpret_cast(buffer) & static_cast(GP_SYSTEM_MEMORY_ALIGNMENT - 1); intptr_t alignPadding = 0; if (offsetFromAlignPoint != 0) alignPadding = static_cast(GP_SYSTEM_MEMORY_ALIGNMENT) - offsetFromAlignPoint; GpAllocator_C_MMBlock *mmBlock = reinterpret_cast(buffer + alignPadding); mmBlock->m_offsetFromAllocLocation = static_cast(alignPadding); return buffer + alignPadding + GpAllocator_C_MMBlock::AlignedSize(); } void GpAllocator_C::Free(void *buf) { if (!buf) return; const size_t mmBlockSize = GpAllocator_C_MMBlock::AlignedSize(); uint8_t *bytes = static_cast(buf); const GpAllocator_C_MMBlock *mmBlock = reinterpret_cast(bytes - GpAllocator_C_MMBlock::AlignedSize()); void *freeLoc = bytes - GpAllocator_C_MMBlock::AlignedSize() - mmBlock->m_offsetFromAllocLocation; realloc(freeLoc, 0); } GpAllocator_C *GpAllocator_C::GetInstance() { return &ms_instance; } GpAllocator_C GpAllocator_C::ms_instance;