mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-12 23:51:37 -07:00
187 lines
4.8 KiB
C
187 lines
4.8 KiB
C
#ifdef INTELLISENSE_DIRECTIVES
|
|
# pragma once
|
|
# include "arena.h"
|
|
#endif
|
|
|
|
// Copyright (c) 2024 Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Arena Functions
|
|
|
|
//- rjf: arena creation/destruction
|
|
|
|
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->base_pos = 0;
|
|
arena->pos = header_size;
|
|
arena->block_size = params.block_size;
|
|
arena->flags = params.flags;
|
|
asan_unpoison_memory_region(base, sizeof(Arena));
|
|
return arena;
|
|
}
|
|
|
|
//- rjf: arena push/pop core functions
|
|
|
|
void*
|
|
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;
|
|
|
|
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) )
|
|
{
|
|
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;
|
|
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 = align_pow2(current->pos, align);
|
|
pos_pst = pos_pre + size;
|
|
}
|
|
|
|
// rjf: push onto current block
|
|
void* result = 0;
|
|
// if(current->cmt >= pos_pst)
|
|
{
|
|
result = (U8*)current + pos_pre;
|
|
current->pos = pos_pst;
|
|
asan_unpoison_memory_region(result, size);
|
|
}
|
|
|
|
// rjf: panic on failure
|
|
#if OS_FEATURE_GRAPHICAL
|
|
if(unlikely(result == 0))
|
|
{
|
|
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
|
os_abort(1);
|
|
}
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
void
|
|
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;
|
|
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->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;
|
|
}
|
|
|
|
return allocated_ptr;
|
|
}
|