From 54d03b35df972dec4e5c9a0e1e27573d19fb2c2b Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 6 Feb 2025 12:34:11 -0500 Subject: [PATCH] successful adapted raddbg Arena to new substrate allocator strat --- code/base/arena.c | 146 +++++++++++++++++++++++++++--------- code/base/arena.h | 11 +-- code/metagen/metagen_main.c | 102 ++++++++++++------------- 3 files changed, 164 insertions(+), 95 deletions(-) diff --git a/code/base/arena.c b/code/base/arena.c index 34bba47..7545475 100644 --- a/code/base/arena.c +++ b/code/base/arena.c @@ -14,13 +14,18 @@ Arena* arena_alloc_(ArenaParams* params) { + SPTR const header_size = align_pow2(size_of(Arena), MD_DEFAULT_MEMORY_ALIGNMENT); + + // TODO(Ed): Do we need to be slapping the arena onto the memory now? + // (its technically not needed a its no longer always backed by vmem) void* base = alloc(params->backing, params->block_size); // rjf: extract arena header & fill Arena* arena = (Arena*) base; arena->prev = nullptr; arena->current = arena; arena->backing = params->backing; - arena->pos = size_of(Arena); + arena->base_pos = 0; + arena->pos = header_size; arena->block_size = params->block_size; arena->flags = params->flags; asan_unpoison_memory_region(base, sizeof(Arena)); @@ -29,62 +34,63 @@ arena_alloc_(ArenaParams* params) //- rjf: arena push/pop core functions -internal void * +void* arena_push(Arena *arena, U64 size, U64 align) { - SPTR header_size = size_of(Arena); + SPTR const header_size = align_pow2(size_of(Arena), MD_DEFAULT_MEMORY_ALIGNMENT); Arena *current = arena->current; - SPTR pos_pre = AlignPow2(current->pos, align); + + SPTR pos_pre = align_pow2(current->pos, align); SPTR pos_pst = pos_pre + size; // rjf: chain, if needed - if ( current->block_size < pos_pst && !(arena->flags & ArenaFlag_NoChain) ) + if ( current->block_size < pos_pst && ! (arena->flags & ArenaFlag_NoChain) ) { SSIZE res_size = current->block_size; - - if(size + > res_size) - { - res_size = size + ARENA_HEADER_SIZE; + if(size + header_size > res_size) { + res_size = size + header_size; } - Arena *new_block = arena_alloc( - .reserve_size = res_size, - .commit_size = cmt_size, - .flags = current->flags - ); - - new_block->base_pos = current->base_pos + current->res; + Arena* new_block = nullptr; - SLLStackPush_N(arena->current, new_block, prev); + B32 + vmem_chain = (arena->flags & ArenaFlag_NoChainVirtual); + vmem_chain &= allocator_type(arena->backing) == AllocatorType_VArena; + if (vmem_chain) { + SPTR const varena_header_size = align_pow2(size_of(VArena), MD_DEFAULT_MEMORY_ALIGNMENT); + U64 const arena_block_size = VARENA_DEFAULT_RESERVE - varena_header_size; + + VArena* new_vm = varena_alloc(.reserve_size = VARENA_DEFAULT_RESERVE, .commit_size = VARENA_DEFAULT_COMMIT); + new_block = arena_alloc(.backing = varena_allocator(new_vm), .block_size = arena_block_size); + } + else { + U64 const arena_block_size = arena->block_size + header_size; + + new_block = arena_alloc(.backing = arena->backing, .block_size = arena_block_size); + } + + new_block->base_pos = current->base_pos + current->block_size; + + sll_stack_push_n(arena->current, new_block, prev); current = new_block; - pos_pre = AlignPow2(current->pos, align); + pos_pre = align_pow2(current->pos, align); pos_pst = pos_pre + size; } - // rjf: commit new pages, if needed - if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages)) - { - U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size); - U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res); - U64 cmt_size = cmt_pst_clamped - current->cmt; - os_commit((U8 *)current + current->cmt, cmt_size); - current->cmt = cmt_pst_clamped; - } - // rjf: push onto current block - void *result = 0; - if(current->cmt >= pos_pst) + void* result = 0; + // if(current->cmt >= pos_pst) { - result = (U8 *)current+pos_pre; + result = (U8*)current + pos_pre; current->pos = pos_pst; - AsanUnpoisonMemoryRegion(result, size); + asan_unpoison_memory_region(result, size); } // rjf: panic on failure #if OS_FEATURE_GRAPHICAL - if(Unlikely(result == 0)) + if(unlikely(result == 0)) { os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure.")); os_abort(1); @@ -97,16 +103,84 @@ arena_push(Arena *arena, U64 size, U64 align) void arena_pop_to(Arena *arena, U64 pos) { - U64 big_pos = clamp_bot(size_of(Arena), pos); + SPTR const header_size = align_pow2(size_of(Arena), MD_DEFAULT_MEMORY_ALIGNMENT); + + U64 big_pos = clamp_bot(header_size, pos); Arena* current = arena->current; - for(Arena* prev = 0; current->pos >= big_pos; current = prev) + for(Arena* prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; alloc_free(current->backing, current); } arena->current = current; - U64 new_pos = big_pos - current->pos; + U64 new_pos = big_pos - current->base_pos; assert_always(new_pos <= current->pos); asan_poison_memory_region((U8*)current + new_pos, (current->pos - new_pos)); current->pos = new_pos; } + +void* arena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags) +{ + Arena* arena = rcast(Arena*, allocator_data); + + void* allocated_ptr = nullptr; + switch (mode) + { + case AllocatorMode_Alloc: + { + allocated_ptr = arena_push(arena, size, alignment); + } + break; + + case AllocatorMode_Free: + { + } + break; + + case AllocatorMode_FreeAll: + { + arena_release(arena); + } + break; + + case AllocatorMode_Resize: + { + + assert(old_memory != nullptr); + assert(old_size > 0); + assert_msg(old_size == size, "Requested resize when none needed"); + + size = align_pow2(size, alignment); + old_size = align_pow2(size, alignment); + + SPTR old_memory_offset = scast(SPTR, old_memory) + old_size; + SPTR current_offset = arena->pos; + + assert_msg(old_memory_offset == current_offset, "Cannot resize existing allocation in VArena unless it was the last allocated"); + + B32 requested_shrink = size >= old_size; + if (requested_shrink) { + + arena->pos -= size; + allocated_ptr = old_memory; + break; + } + + allocated_ptr = old_memory; + arena->pos += size; + } + break; + + case AllocatorMode_QueryType: + { + return (void*) AllocatorType_Arena; + } + break; + + case AllocatorMode_QuerySupport: + { + return (void*) (AllocatorQuery_Alloc | AllocatorQuery_Resize | AllocatorQuery_FreeAll); + } + break; + } +} diff --git a/code/base/arena.h b/code/base/arena.h index b6bcc8f..9e3ae0a 100644 --- a/code/base/arena.h +++ b/code/base/arena.h @@ -8,11 +8,6 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -//////////////////////////////// -//~ rjf: Constants - -#define ARENA_HEADER_SIZE 64 - //////////////////////////////// //~ rjf: Types @@ -52,11 +47,12 @@ struct Arena Arena* prev; // previous arena in chain Arena* current; // current arena in chain AllocatorInfo backing; + SSIZE base_pos; SSIZE pos; SSIZE block_size; ArenaFlags flags; }; -static_assert(size_of(Arena) <= ARENA_HEADER_SIZE, "sizeof(Arena) <= ARENA_HEADER_SIZE"); +// static_assert(size_of(Arena) <= ARENA_HEADER_SIZE, "sizeof(Arena) <= ARENA_HEADER_SIZE"); typedef struct TempArena TempArena; struct TempArena @@ -120,9 +116,8 @@ arena_release(Arena* arena) { inline U64 arena_pos(Arena *arena) { - U64 const header_size = size_of(Arena); Arena* current = arena->current; - U64 pos = current + header_size + current->pos; + U64 pos = current->base_pos + current->pos; return pos; } diff --git a/code/metagen/metagen_main.c b/code/metagen/metagen_main.c index 1ea423b..f79c37f 100644 --- a/code/metagen/metagen_main.c +++ b/code/metagen/metagen_main.c @@ -27,57 +27,57 @@ internal void entry_point(CmdLine *cmdline) { - ////////////////////////////// - //- rjf: set up state - // - MG_MsgList msgs = {0}; - mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64)); - mg_state = push_array(mg_arena, MG_State, 1); - mg_state->slots_count = 256; - mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count); - - ////////////////////////////// - //- rjf: extract paths - // - String8 build_dir_path = os_get_process_info()->binary_path; - String8 project_dir_path = str8_chop_last_slash(build_dir_path); - String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path); - - ////////////////////////////// - //- rjf: search code directories for all files to consider - // - String8List file_paths = {0}; - DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count)) - { - typedef struct Task Task; - struct Task - { - Task *next; - String8 path; - }; - Task start_task = {0, code_dir_path}; - Task *first_task = &start_task; - Task *last_task = &start_task; - for(Task *task = first_task; task != 0; task = task->next) - { - OS_FileIter *it = os_file_iter_begin(mg_arena, task->path, 0); - for(OS_FileInfo info = {0}; os_file_iter_next(mg_arena, it, &info);) - { - String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name); - if(info.props.flags & FilePropertyFlag_IsFolder) - { - Task *next_task = push_array(mg_arena, Task, 1); - SLLQueuePush(first_task, last_task, next_task); - next_task->path = file_path; - } - else - { - str8_list_push(mg_arena, &file_paths, file_path); - } - } - os_file_iter_end(it); - } - } + ////////////////////////////// + //- rjf: set up state + // + MG_MsgList msgs = {0}; + mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64)); + mg_state = push_array(mg_arena, MG_State, 1); + mg_state->slots_count = 256; + mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count); + + ////////////////////////////// + //- rjf: extract paths + // + String8 build_dir_path = os_get_process_info()->binary_path; + String8 project_dir_path = str8_chop_last_slash(build_dir_path); + String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path); + + ////////////////////////////// + //- rjf: search code directories for all files to consider + // + String8List file_paths = {0}; + DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count)) + { + typedef struct Task Task; + struct Task + { + Task *next; + String8 path; + }; + Task start_task = {0, code_dir_path}; + Task* first_task = &start_task; + Task* last_task = &start_task; + for(Task *task = first_task; task != 0; task = task->next) + { + OS_FileIter* it = os_file_iter_begin(mg_arena, task->path, 0); + for(OS_FileInfo info = {0}; os_file_iter_next(mg_arena, it, &info);) + { + String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name); + if(info.props.flags & FilePropertyFlag_IsFolder) + { + Task *next_task = push_array(mg_arena, Task, 1); + SLLQueuePush(first_task, last_task, next_task); + next_task->path = file_path; + } + else + { + str8_list_push(mg_arena, &file_paths, file_path); + } + } + os_file_iter_end(it); + } + } ////////////////////////////// //- rjf: parse all metadesk files