From 033bf5d6ef7d189eb899a4ea6046fa6a0a29f968 Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Tue, 15 Sep 2026 22:48:03 -0700 Subject: [PATCH] Add tests for Heap allocator Add Heap::getMaxSize() Add Heap::getUsed() Add minSize argument to Heap::init() --- include/block.h | 1 + include/heap.h | 12 +++++++++++- src/heap.cpp | 28 ++++++++++++++++++++++++++-- src/mimir_impl.h | 1 + tests/CMakeLists.txt | 3 ++- tests/arena_test.cpp | 8 ++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/block.h b/include/block.h index 0865b6e..3c1e817 100644 --- a/include/block.h +++ b/include/block.h @@ -35,6 +35,7 @@ #include #if defined(_WIN32) || defined(_WIN64) +#define NOMINMAX #include #endif diff --git a/include/heap.h b/include/heap.h index 0a001c7..15af098 100644 --- a/include/heap.h +++ b/include/heap.h @@ -46,7 +46,7 @@ public: Heap(); ~Heap(); - bool init(size_t maxSize = 1ULL << 32); + bool init(size_t minSize = 1ULL << 24, size_t maxSize = 1ULL << 32); // Allocate `size` bytes std::byte* alloc(size_t size); @@ -60,8 +60,18 @@ public: // Free the allocation at `address` void free(std::byte* address); + // Get the actual used size. + // This may differ from the sum of allocations due to alignment requirements. + size_t getUsed() const; + + // Get the actual maximum size. + // This may be greater than the maxSize passed into init, due to page size alignment. + size_t getMaxSize() const; + private: Region m_region; + size_t m_minSize; + size_t m_usedSize; // Add a free block to the index void insertFreeBlock(TLSFBlock* block); diff --git a/src/heap.cpp b/src/heap.cpp index 0fdd5b1..fa4db50 100644 --- a/src/heap.cpp +++ b/src/heap.cpp @@ -32,6 +32,7 @@ #include "../include/mimir.h" #include "mimir_impl.h" +#include #include #include #include @@ -94,6 +95,8 @@ uint64_t blockSizeToIndex(uint64_t size) */ Heap::Heap() + : m_minSize(0) + , m_usedSize(0) { } @@ -101,12 +104,18 @@ Heap::~Heap() { } -bool Heap::init(size_t maxSize) +bool Heap::init(size_t minSize, size_t maxSize) { + assert(maxSize >= minSize); + assert(m_usedSize == 0); + + m_minSize = sizeof(TLSFIndex) + 16; + m_minSize = std::max(m_minSize, minSize); + m_minSize = KRAKEN_MEM_ROUND_UP_PAGE(m_minSize); if (!m_region.init(maxSize)) { return false; } - if (!m_region.resize(sizeof(TLSFIndex) + 16)) { + if (!m_region.resize(m_minSize)) { return false; } TLSFIndex* index = (TLSFIndex*)m_region.getAddress(); @@ -124,6 +133,20 @@ bool Heap::init(size_t maxSize) return true; } +// Get the actual maximum size. +// This may be greater than the maxSize passed into init, due to page size alignment. +size_t Heap::getMaxSize() const +{ + return m_region.getSize(); +} + +// Get the actual used size. +// This may differ from the sum of allocations due to alignment requirements. +size_t Heap::getUsed() const +{ + return m_usedSize; +} + void Heap::insertFreeBlock(TLSFBlock* block) { // Add the block to the index @@ -281,6 +304,7 @@ std::byte* Heap::alloc(size_t size) } block->size = size; + m_usedSize += size; return (std::byte*)block + 16; } diff --git a/src/mimir_impl.h b/src/mimir_impl.h index 1882f81..ec6bb04 100644 --- a/src/mimir_impl.h +++ b/src/mimir_impl.h @@ -39,6 +39,7 @@ #endif #if defined(_WIN32) || defined(_WIN64) +#define NOMINMAX #include #include #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68887b9..6146a9e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,8 +14,9 @@ enable_testing() add_executable( mimir_test - "region_test.cpp" "arena_test.cpp" + "heap_test.cpp" + "region_test.cpp" "test_util.cpp") target_link_libraries( mimir_test diff --git a/tests/arena_test.cpp b/tests/arena_test.cpp index 2743a7a..9f80569 100644 --- a/tests/arena_test.cpp +++ b/tests/arena_test.cpp @@ -6,6 +6,14 @@ namespace mimir_tests { +TEST(Arena, InitialState) +{ + mimir::init(); + mimir::Arena arena; + EXPECT_TRUE(arena.init()); + EXPECT_EQ(arena.getUsed(), 0); +} + TEST(Arena, OutOfMemory) { mimir::init();