From 4a75eddd8f50fd351d3ddc0a17d675562302a0a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 16 Jun 2026 23:46:52 +0200 Subject: [PATCH] Implement memory decommit --- src/arena.c | 13 ++++++++++++- src/arena.h | 3 +++ src/main.c | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/arena.c b/src/arena.c index fc0390f..3ca6661 100644 --- a/src/arena.c +++ b/src/arena.c @@ -115,7 +115,7 @@ void arena_reset_to(Arena *arena, U64 total_offset) MemoryBlock *prev = block->prev; if (block->arena_offset >= total_offset) { - ASAN_UNPOISON_MEMORY_REGION(block->base, block->size); + ASAN_UNPOISON_MEMORY_REGION(block->base, block->committed_end); memory_free(block->base, block->size); arena->current = prev; } else { @@ -123,8 +123,19 @@ void arena_reset_to(Arena *arena, U64 total_offset) new_pos = Max(MemoryBlock_Header_Size, new_pos); // Disallow arbitrary pops to positions that previously were not commited. Assert(new_pos <= block->committed_end); + Assert(new_pos <= block->size); block->first_free = new_pos; ASAN_POISON_MEMORY_REGION(&block->base[block->first_free], memoryblock_available(block)); + + if ((arena->flags & ArenaFlag_NoDecommit) == 0) { + U32 aligned_pos = RoundUpToMultiple(block->first_free, arena->commit_size); + if (aligned_pos < block->committed_end) { + ASAN_UNPOISON_MEMORY_REGION(&block->base[aligned_pos], block->committed_end); + memory_decommit(&block->base[aligned_pos], block->committed_end - aligned_pos); + block->committed_end = aligned_pos; + } + } + break; } diff --git a/src/arena.h b/src/arena.h index 0a666ed..f2f64db 100644 --- a/src/arena.h +++ b/src/arena.h @@ -4,6 +4,9 @@ typedef U32 ArenaFlags; typedef struct ArenaOptions ArenaOptions; +enum { + ArenaFlag_NoDecommit, // arena_ temp_end/reset/reset_to doesn't decommit memory +}; struct ArenaOptions { U32 size; U32 commit_size; diff --git a/src/main.c b/src/main.c index 1284859..8210d79 100644 --- a/src/main.c +++ b/src/main.c @@ -162,6 +162,34 @@ static void arena_test_4(void) arena_free(&arena); } + +static void arena_test_decommit(void) +{ + TRACEF("\n"); + + U32 page_size = platform_page_size(); + ArenaOptions arena_params = {}; + U32 arena_size = MB(1) + MemoryBlock_Header_Size; + U32 commit_size = KB(64); + arena_params.size = arena_size; + arena_params.commit_size = commit_size; + Arena arena; + arena_init(&arena, &arena_params); + void *ptr = arena_push(&arena, commit_size * 10, 8); + MemoryZero(ptr, commit_size * 10); + arena_reset(&arena); + + void *pre_ptr = arena_push(&arena, 5, 4); + + ATemp tmp = arena_temp_begin(&arena); + ptr = arena_push(&arena, commit_size * 2 + 13, 8); + MemoryZero(ptr, commit_size * 2 + 13); + arena_temp_end(&tmp); + MemoryZero(pre_ptr, 5); + + arena_free(&arena); +} + void miniarena_test1(void) { #define arena_size 4096 @@ -290,8 +318,10 @@ int main(int argc, char *argv[]) // arena_test_2(); // arena_test_3(); // arena_test_4(); -// miniarena_test1(); - apool_test(); - apool_test_autogrow(); + arena_test_decommit(); + + // miniarena_test1(); + // apool_test(); + // apool_test_autogrow(); }