diff --git a/Engine/src/delta/core/FreeListAllocator.cpp b/Engine/src/delta/core/FreeListAllocator.cpp index 3a07bc0..604344f 100644 --- a/Engine/src/delta/core/FreeListAllocator.cpp +++ b/Engine/src/delta/core/FreeListAllocator.cpp @@ -23,13 +23,18 @@ using namespace delta::core; using MemoryState = MemoryManager::MemoryState; using Node = FreeListAllocator::Node; +using BucketMetadata = FreeListAllocator::BucketMetadata; DLT_FORCE_INLINE void* AllocatePageForBucket(FreeListAllocator* allocator, uint32_t bucketIx, uint64_t size) { void* rawPage = MemoryManager::AllocatePageLockFree(allocator->memState); - uint64_t numChunks = allocator->pageSize / size; - uint8_t* walker = static_cast(rawPage); + BucketMetadata* meta = reinterpret_cast(rawPage); + meta->magic = BucketMetadata::MAGIC_VALUE; + meta->bucketIx = bucketIx; + + uint64_t numChunks = allocator->remaining / size; + uint8_t* walker = static_cast(rawPage) + sizeof(BucketMetadata); Node* head = reinterpret_cast(walker); Node* current = head; @@ -43,6 +48,7 @@ DLT_FORCE_INLINE void* AllocatePageForBucket(FreeListAllocator* allocator, uint3 } current->next = nullptr; + allocator->buckets[bucketIx] = head; return head; } @@ -50,6 +56,7 @@ void delta::core::FreeList_Init(FreeListAllocator* allocator, MemoryState* memSt { allocator->memState = memState; allocator->pageSize = memState->pageSize; + allocator->remaining = memState->pageSize - sizeof(BucketMetadata); } void* delta::core::FreeList_Allocate(FreeListAllocator* allocator, uint64_t size, uint64_t alignment) @@ -76,3 +83,20 @@ void* delta::core::FreeList_Allocate(FreeListAllocator* allocator, uint64_t size return MemoryManager::AllocatePageLockFree(allocator->memState); } + +void delta::core::FreeList_Free(FreeListAllocator* allocator, void* ptr) +{ + if (!ptr) + return; + + uintptr_t address = reinterpret_cast(ptr); + uintptr_t basePage = address & ~0xfffull; + + const BucketMetadata* metadata = reinterpret_cast(basePage); + assert(metadata->magic == BucketMetadata::MAGIC_VALUE); + + uint32_t bucketIx = metadata->bucketIx; + Node* freeNode = reinterpret_cast(ptr); + freeNode->next = allocator->buckets[bucketIx]; + allocator->buckets[bucketIx] = freeNode; +} diff --git a/Engine/src/delta/core/FreeListAllocator.h b/Engine/src/delta/core/FreeListAllocator.h index 8c115b3..47dec73 100644 --- a/Engine/src/delta/core/FreeListAllocator.h +++ b/Engine/src/delta/core/FreeListAllocator.h @@ -28,14 +28,24 @@ namespace delta::core static constexpr uint32_t BUCKET_COUNT = 7ull; // log2(2048) - log2(16) = 7, calculated manually for simplicity struct Node { Node* next; }; + struct alignas(16) BucketMetadata + { + static constexpr char MAGIC_VALUE_STR[sizeof(uint64_t)] = "DLT_SFA"; + static constexpr uint64_t MAGIC_VALUE = std::bit_cast(MAGIC_VALUE_STR); + + uint64_t magic; + uint32_t bucketIx; + }; MemoryManager::MemoryState* memState; Node* buckets[BUCKET_COUNT]; uint64_t pageSize; + uint64_t remaining; // pageSize - metadata size }; void FreeList_Init(FreeListAllocator* allocator, MemoryManager::MemoryState* memState); void* FreeList_Allocate(FreeListAllocator* allocator, uint64_t size, uint64_t alignment); + void FreeList_Free(FreeListAllocator* allocator, void* ptr); }