From 632bc6d47fa4d4c68efec8b2d209c4b0106014b7 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 10 Feb 2025 12:00:39 -0500 Subject: [PATCH] memory fixes --- code/base/arena.c | 79 +++++++++++++++++++++++------------- code/base/arena.h | 2 + code/base/memory_substrate.c | 29 +++++-------- code/base/memory_substrate.h | 2 + code/mdesk/mdesk.c | 7 ++-- code/mdesk/mdesk.h | 2 +- code/os/os.h | 4 +- gen_c11/gen_c11.c | 1 - tests/code_sanity.c | 15 ++++--- 9 files changed, 82 insertions(+), 59 deletions(-) diff --git a/code/base/arena.c b/code/base/arena.c index 8d1ed3c..0f43e63 100644 --- a/code/base/arena.c +++ b/code/base/arena.c @@ -21,12 +21,16 @@ arena__alloc(ArenaParams* optional_params) U64 const varena_reserve_size = VARENA_DEFAULT_RESERVE; + B32 is_virtual = allocator_type(params.backing) & AllocatorType_VArena; + params.flags |= ArenaFlag_Virtual * is_virtual; + + if (params.backing.proc == nullptr) params.backing = default_allocator(); if (params.block_size == 0 ) params.block_size = ARENA_DEFAULT_BLOCK_SIZE; - // 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); + SSIZE alloc_size = is_virtual ? header_size : params.block_size; + + void* base = alloc(params.backing, alloc_size); // rjf: extract arena header & fill Arena* arena = (Arena*) base; arena->prev = nullptr; @@ -43,58 +47,61 @@ arena__alloc(ArenaParams* optional_params) //- rjf: arena push/pop core functions void* -arena_push(Arena *arena, SSIZE size, SSIZE align) +arena_push(Arena* arena, SSIZE size, SSIZE align) { SPTR const header_size = align_pow2(size_of(Arena), MD_DEFAULT_MEMORY_ALIGNMENT); - Arena *current = arena->current; + Arena* current = arena->current; + SPTR curr_sptr = scast(SPTR, current); - SPTR pos_pre = align_pow2(current->pos, align); - SPTR pos_pst = pos_pre + size; + SSIZE aligned_size = align_pow2(size, align); + + SPTR pos_pre = current->pos; + SPTR pos_pst = pos_pre + aligned_size; + + B32 is_virtual = arena->flags & ArenaFlag_Virtual; // rjf: chain, if needed if ( current->block_size < pos_pst && ! (arena->flags & ArenaFlag_NoChain) ) { - SSIZE res_size = current->block_size; - if(size + header_size > res_size) { - res_size = size + header_size; - } - Arena* new_block = nullptr; - B32 - vmem_chain = (arena->flags & ArenaFlag_NoChainVirtual); - vmem_chain &= allocator_type(arena->backing) == AllocatorType_VArena; + B32 vmem_chain = is_virtual && (arena->flags & ArenaFlag_NoChainVirtual); 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; + SPTR 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); + VArena* vcurrent = rcast(VArena*, arena->backing.data); + + VArena* new_vm = varena_alloc(.reserve_size = vcurrent->reserve, .commit_size = vcurrent->commit_size); 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; - + SPTR 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 = align_pow2(current->pos, align); - pos_pst = pos_pre + size; + pos_pre = current->pos; + pos_pst = pos_pre + aligned_size; } - + // rjf: push onto current block void* result = 0; - // if(current->cmt >= pos_pst) { - result = (U8*)current + pos_pre; + result = scast(void*, curr_sptr + pos_pre); current->pos = pos_pst; asan_unpoison_memory_region(result, size); } + + if (is_virtual) { + // Sync virtual arena + void* vresult = alloc_align(arena->backing, size, align); + assert(vresult == result); + } // rjf: panic on failure #if OS_FEATURE_GRAPHICAL @@ -113,18 +120,32 @@ arena_pop_to(Arena *arena, SSIZE 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; + Arena* current = arena->current; + AllocatorInfo backing = current->backing; + B32 is_virtual = allocator_type(backing) & AllocatorType_VArena; + + SSIZE big_pos = clamp_bot(header_size, pos); + // If base position is larger than the position to pop to: + // We are in a previous arena and msut free the current for(Arena* prev = 0; current->base_pos >= big_pos; current = prev) { prev = current->prev; - alloc_free(current->backing, current); + + if (is_virtual) { + varena_release(rcast(VArena*, current->backing.data)); + } + else if (allocator_query_support(backing) & AllocatorQuery_Free) { + alloc_free(current->backing, current); + } } arena->current = current; - U64 new_pos = big_pos - current->base_pos; + SSIZE 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; + if (is_virtual) { + varena_rewind(rcast(VArena*, current->backing.data), current->pos); + } } void* arena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags) diff --git a/code/base/arena.h b/code/base/arena.h index 347208b..a8b5506 100644 --- a/code/base/arena.h +++ b/code/base/arena.h @@ -19,6 +19,8 @@ enum // Only relevant if backing is virtual memory, will prevent allocating a new backing VArena when the current block exhausts // Will assume backing can chain multiple block_size arenas however. If there is an allocation failure it will assert. ArenaFlag_NoChainVirtual = (1 << 1), + // Backing allocator identified as VArena during initialization + ArenaFlag_Virtual = (1 << 0), }; typedef struct ArenaParams ArenaParams; diff --git a/code/base/memory_substrate.c b/code/base/memory_substrate.c index 57ff219..4dd3dcf 100644 --- a/code/base/memory_substrate.c +++ b/code/base/memory_substrate.c @@ -249,8 +249,9 @@ varena__alloc(VArenaParams params) reserve_size = align_pow2(reserve_size, os_get_system_info()->page_size); commit_size = align_pow2(commit_size, os_get_system_info()->page_size); - base = os_reserve(reserve_size); - os_commit(base, commit_size); + base = os_reserve(reserve_size); + B32 commit_result = os_commit(base, commit_size); + assert(commit_result == 1); asan_poison_memory_region(base, params.commit_size); } @@ -302,7 +303,8 @@ varena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE requested_ UPTR current_offset = vm->reserve_start + vm->commit_used; UPTR size_to_allocate = requested_size; UPTR to_be_used = vm->commit_used + size_to_allocate; - assert(to_be_used < vm->reserve); + SPTR reserve_left = vm->reserve - vm->committed; + assert(to_be_used < reserve_left); UPTR header_offset = vm->reserve_start - scast(UPTR, vm); @@ -310,19 +312,20 @@ varena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE requested_ B32 needs_more_commited = commit_left < size_to_allocate; if (needs_more_commited) { - SPTR reserve_left = vm->reserve - vm->committed; UPTR next_commit_size; if (vm->flags & VArenaFlag_LargePages) { - next_commit_size = reserve_left > 0 ? md_max(vm->commit_size, size_to_allocate) : scast(UPTR, align_pow2( -reserve_left, os_get_system_info()->large_page_size)); + next_commit_size = reserve_left > 0 ? md_max(vm->commit_size, size_to_allocate) : scast(UPTR, align_pow2( abs(reserve_left), os_get_system_info()->large_page_size)); } else { next_commit_size = reserve_left > 0 ? md_max(vm->commit_size, size_to_allocate) : scast(UPTR, align_pow2(abs(reserve_left), os_get_system_info()->page_size)); } if (next_commit_size) { - B32 commit_result = os_commit(vm, next_commit_size); + void* next_commit_start = rcast(void*, rcast(UPTR, vm) + vm->committed); + B32 commit_result = os_commit(next_commit_start, next_commit_size); if (commit_result == false) { break; } + vm->committed += next_commit_size; } } @@ -391,11 +394,6 @@ varena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE requested_ } break; - // case AllocatorMode_Pop: - // break; - // case AllocatorMode_Pop_To: - // break; - case AllocatorMode_QueryType: { return (void*) AllocatorType_VArena; @@ -474,18 +472,13 @@ farena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZ } break; - // case AllocatorMode_Pop: - // break; - // case AllocatorMode_Pop_To: - // break; - case AllocatorMode_QueryType: return (void*) AllocatorType_FArena; break; case AllocatorMode_QuerySupport: - return (void*) (AllocatorQuery_Alloc | AllocatorQuery_FreeAll | AllocatorQuery_Resize - // | AllocatorQuery_Pop | AllocatorQuery_Pop_To + return (void*) ( + AllocatorQuery_Alloc | AllocatorQuery_FreeAll | AllocatorQuery_Resize | AllocatorQuery_ResizeGrow | AllocatorQuery_ResizeShrink ); break; } diff --git a/code/base/memory_substrate.h b/code/base/memory_substrate.h index c0f3944..8ceb087 100644 --- a/code/base/memory_substrate.h +++ b/code/base/memory_substrate.h @@ -194,6 +194,8 @@ MD_API VArena* varena__alloc(VArenaParams params PARAM_DEFAULT); MD_API void varena_commit (VArena* vm, SSIZE commit_size); MD_API void varena_release(VArena* vm); +force_inline void varena_rewind(VArena* vm, SSIZE pos) { vm->commit_used = pos; } + MD_API void* varena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags); #define varena_allocator(vm) (AllocatorInfo) { varena_allocator_proc, vm } diff --git a/code/mdesk/mdesk.c b/code/mdesk/mdesk.c index a399315..599affe 100644 --- a/code/mdesk/mdesk.c +++ b/code/mdesk/mdesk.c @@ -18,9 +18,10 @@ void init(Context* ctx) } -// void deinit(Context* ctx) -// { -// } +void deinit(Context* ctx) +{ + // Nothing for now +} //////////////////////////////// //~ rjf: Message Type Functions diff --git a/code/mdesk/mdesk.h b/code/mdesk/mdesk.h index 1a56a52..b40526c 100644 --- a/code/mdesk/mdesk.h +++ b/code/mdesk/mdesk.h @@ -271,7 +271,7 @@ nil_node() // the metadesk os runtime provided entry_point interface MD_API void init(Context* ctx); -// MD_API void deinit(Context* ctx); +MD_API void deinit(Context* ctx); // Does nothing for now. //////////////////////////////// //~ rjf: Message Type Functions diff --git a/code/os/os.h b/code/os/os.h index 013f13c..38280fe 100644 --- a/code/os/os.h +++ b/code/os/os.h @@ -264,10 +264,12 @@ MD_API String8 os_string_from_file_range__ainfo(AllocatorInfo ainfo, OS_Handle f #define os_data_from_file_path(allocator, path) _Generic(allocator, Arena*: os_data_from_file_path__arena, AllocatorInfo: os_data_from_file_path__ainfo, default: assert_generic_selection_fail) resolved_function_call(allocator, path) #define os_string_from_file_range(allocator, file, range) _Generic(allocator, Arena*: os_string_from_file_range__arena, AllocatorInfo: os_string_from_file_range__ainfo, default: assert_generic_selection_fail) resolved_function_call(allocator, file, range) +force_inline String8 os_data_from_file_path__arena(Arena* arena, String8 path) { return os_data_from_file_path__ainfo(arena_allocator(arena), path); } + inline String8 os_data_from_file_path__ainfo(AllocatorInfo ainfo, String8 path) { - OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, path); + OS_Handle file = os_file_open(OS_AccessFlag_Read | OS_AccessFlag_ShareRead, path); FileProperties props = os_properties_from_file(file); String8 data = os_string_from_file_range(ainfo, file, r1u64(0, props.size)); os_file_close(file); diff --git a/gen_c11/gen_c11.c b/gen_c11/gen_c11.c index 55af756..3b648fe 100644 --- a/gen_c11/gen_c11.c +++ b/gen_c11/gen_c11.c @@ -15,6 +15,5 @@ int main() gen_Context ctx = {0}; gen_init(& ctx); - return 0; } diff --git a/tests/code_sanity.c b/tests/code_sanity.c index 941246f..c93fb64 100644 --- a/tests/code_sanity.c +++ b/tests/code_sanity.c @@ -4,9 +4,11 @@ #include "metadesk.c" // This program expects to be run from the build directory (where it would be after being built) -#define path_examples "../examples" -#define path_intro path_examples "/intro" -#define path_hello_world_medesk path_intro "/hello_world.mdesk" +#define path_examples "../examples" +#define path_intro path_examples "/intro" +#define path_hello_world_mdesk path_intro "/hello_world.mdesk" + +#define text str8_lit int main() { @@ -14,9 +16,10 @@ int main() ctx.os_ctx.enable_large_pages = true; init(& ctx); - - printf("metadesk: got past init!"); - // deinit(& ctx); + Arena* arena = arena_alloc(); + String8 hello_world_mdesk = os_data_from_file_path(arena, text(path_hello_world_mdesk)); + + deinit(& ctx); }