successful adapted raddbg Arena to new substrate allocator strat

This commit is contained in:
2025-02-06 12:34:11 -05:00
parent bfef61bd0b
commit 54d03b35df
3 changed files with 164 additions and 95 deletions
+110 -36
View File
@@ -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;
}
}
+3 -8
View File
@@ -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;
}
+51 -51
View File
@@ -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