successful adapted raddbg Arena to new substrate allocator strat

This commit is contained in:
ed
2025-02-06 12:34:11 -05:00
parent bfef61bd0b
commit 54d03b35df
3 changed files with 164 additions and 95 deletions
+109 -35
View File
@@ -14,13 +14,18 @@
Arena* Arena*
arena_alloc_(ArenaParams* params) 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); void* base = alloc(params->backing, params->block_size);
// rjf: extract arena header & fill // rjf: extract arena header & fill
Arena* arena = (Arena*) base; Arena* arena = (Arena*) base;
arena->prev = nullptr; arena->prev = nullptr;
arena->current = arena; arena->current = arena;
arena->backing = params->backing; arena->backing = params->backing;
arena->pos = size_of(Arena); arena->base_pos = 0;
arena->pos = header_size;
arena->block_size = params->block_size; arena->block_size = params->block_size;
arena->flags = params->flags; arena->flags = params->flags;
asan_unpoison_memory_region(base, sizeof(Arena)); asan_unpoison_memory_region(base, sizeof(Arena));
@@ -29,62 +34,63 @@ arena_alloc_(ArenaParams* params)
//- rjf: arena push/pop core functions //- rjf: arena push/pop core functions
internal void * void*
arena_push(Arena *arena, U64 size, U64 align) 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; 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; SPTR pos_pst = pos_pre + size;
// rjf: chain, if needed // 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; SSIZE res_size = current->block_size;
if(size + header_size > res_size) {
if(size + > res_size) res_size = size + header_size;
{
res_size = size + ARENA_HEADER_SIZE;
} }
Arena *new_block = arena_alloc( Arena* new_block = nullptr;
.reserve_size = res_size,
.commit_size = cmt_size,
.flags = current->flags
);
new_block->base_pos = current->base_pos + current->res; 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;
SLLStackPush_N(arena->current, new_block, prev); 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; current = new_block;
pos_pre = AlignPow2(current->pos, align); pos_pre = align_pow2(current->pos, align);
pos_pst = pos_pre + size; 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 // rjf: push onto current block
void *result = 0; void* result = 0;
if(current->cmt >= pos_pst) // if(current->cmt >= pos_pst)
{ {
result = (U8 *)current+pos_pre; result = (U8*)current + pos_pre;
current->pos = pos_pst; current->pos = pos_pst;
AsanUnpoisonMemoryRegion(result, size); asan_unpoison_memory_region(result, size);
} }
// rjf: panic on failure // rjf: panic on failure
#if OS_FEATURE_GRAPHICAL #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_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
os_abort(1); os_abort(1);
@@ -97,16 +103,84 @@ arena_push(Arena *arena, U64 size, U64 align)
void void
arena_pop_to(Arena *arena, U64 pos) 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; 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; prev = current->prev;
alloc_free(current->backing, current); alloc_free(current->backing, current);
} }
arena->current = 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); assert_always(new_pos <= current->pos);
asan_poison_memory_region((U8*)current + new_pos, (current->pos - new_pos)); asan_poison_memory_region((U8*)current + new_pos, (current->pos - 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;
}
}
+3 -8
View File
@@ -8,11 +8,6 @@
// Copyright (c) 2024 Epic Games Tools // Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/) // Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Constants
#define ARENA_HEADER_SIZE 64
//////////////////////////////// ////////////////////////////////
//~ rjf: Types //~ rjf: Types
@@ -52,11 +47,12 @@ struct Arena
Arena* prev; // previous arena in chain Arena* prev; // previous arena in chain
Arena* current; // current arena in chain Arena* current; // current arena in chain
AllocatorInfo backing; AllocatorInfo backing;
SSIZE base_pos;
SSIZE pos; SSIZE pos;
SSIZE block_size; SSIZE block_size;
ArenaFlags flags; 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; typedef struct TempArena TempArena;
struct TempArena struct TempArena
@@ -120,9 +116,8 @@ arena_release(Arena* arena) {
inline U64 inline U64
arena_pos(Arena *arena) { arena_pos(Arena *arena) {
U64 const header_size = size_of(Arena);
Arena* current = arena->current; Arena* current = arena->current;
U64 pos = current + header_size + current->pos; U64 pos = current->base_pos + current->pos;
return pos; return pos;
} }
+49 -49
View File
@@ -27,57 +27,57 @@
internal void internal void
entry_point(CmdLine *cmdline) entry_point(CmdLine *cmdline)
{ {
////////////////////////////// //////////////////////////////
//- rjf: set up state //- rjf: set up state
// //
MG_MsgList msgs = {0}; MG_MsgList msgs = {0};
mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64)); mg_arena = arena_alloc(.reserve_size = GB(64), .commit_size = MB(64));
mg_state = push_array(mg_arena, MG_State, 1); mg_state = push_array(mg_arena, MG_State, 1);
mg_state->slots_count = 256; mg_state->slots_count = 256;
mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count); mg_state->slots = push_array(mg_arena, MG_LayerSlot, mg_state->slots_count);
////////////////////////////// //////////////////////////////
//- rjf: extract paths //- rjf: extract paths
// //
String8 build_dir_path = os_get_process_info()->binary_path; String8 build_dir_path = os_get_process_info()->binary_path;
String8 project_dir_path = str8_chop_last_slash(build_dir_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); String8 code_dir_path = push_str8f(mg_arena, "%S/src", project_dir_path);
////////////////////////////// //////////////////////////////
//- rjf: search code directories for all files to consider //- rjf: search code directories for all files to consider
// //
String8List file_paths = {0}; String8List file_paths = {0};
DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count)) DeferLoop(printf("searching %.*s...", str8_varg(code_dir_path)), printf(" %i files found\n", (int)file_paths.node_count))
{ {
typedef struct Task Task; typedef struct Task Task;
struct Task struct Task
{ {
Task *next; Task *next;
String8 path; String8 path;
}; };
Task start_task = {0, code_dir_path}; Task start_task = {0, code_dir_path};
Task *first_task = &start_task; Task* first_task = &start_task;
Task *last_task = &start_task; Task* last_task = &start_task;
for(Task *task = first_task; task != 0; task = task->next) for(Task *task = first_task; task != 0; task = task->next)
{ {
OS_FileIter *it = os_file_iter_begin(mg_arena, task->path, 0); 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);) 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); String8 file_path = push_str8f(mg_arena, "%S/%S", task->path, info.name);
if(info.props.flags & FilePropertyFlag_IsFolder) if(info.props.flags & FilePropertyFlag_IsFolder)
{ {
Task *next_task = push_array(mg_arena, Task, 1); Task *next_task = push_array(mg_arena, Task, 1);
SLLQueuePush(first_task, last_task, next_task); SLLQueuePush(first_task, last_task, next_task);
next_task->path = file_path; next_task->path = file_path;
} }
else else
{ {
str8_list_push(mg_arena, &file_paths, file_path); str8_list_push(mg_arena, &file_paths, file_path);
} }
} }
os_file_iter_end(it); os_file_iter_end(it);
} }
} }
////////////////////////////// //////////////////////////////
//- rjf: parse all metadesk files //- rjf: parse all metadesk files