mirror of
https://github.com/Ed94/metadesk.git
synced 2026-06-12 23:51:37 -07:00
frying my brain coming up with a decent compromise on arena usage...
This commit is contained in:
Vendored
+4
-1
@@ -21,6 +21,9 @@
|
||||
"os.h": "c",
|
||||
"os_core.h": "c",
|
||||
"file.h": "c",
|
||||
"xiosbase": "c"
|
||||
"xiosbase": "c",
|
||||
"iterator": "c",
|
||||
"memory": "c",
|
||||
"format": "c"
|
||||
}
|
||||
}
|
||||
+23
-122
@@ -11,134 +11,35 @@
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
|
||||
#if 0
|
||||
internal Arena*
|
||||
arena_alloc_(ArenaParams *params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
|
||||
// rjf: reserve/commit initial block
|
||||
void *base = params->optional_backing_buffer;
|
||||
if(base == 0)
|
||||
{
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
base = os_reserve_large(reserve_size);
|
||||
os_commit_large(base, commit_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = os_reserve(reserve_size);
|
||||
os_commit(base, commit_size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
}
|
||||
#endif
|
||||
|
||||
Arena*
|
||||
arena_alloc_(ArenaParams* params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
B32 is_virtual = false;
|
||||
|
||||
// This composite arena has the ability to decide a default behavior for allocation
|
||||
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = align_pow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = align_pow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = align_pow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = align_pow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
void* base = alloc(params->backing, params->block_size);
|
||||
|
||||
// rjf: reserve/commit initial block
|
||||
void *base = params->optional_backing_buffer;
|
||||
if(base == 0)
|
||||
{
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
base = os_reserve_large(reserve_size);
|
||||
os_commit_large(base, commit_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = os_reserve(reserve_size);
|
||||
os_commit(base, commit_size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
if(unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
}
|
||||
// rjf: extract arena header & fill
|
||||
Arena* arena = (Arena*) base;
|
||||
arena->current = arena;
|
||||
arena->backing = params->backing;
|
||||
arena->pos = size_of(Arena);
|
||||
arena->block_size = params->block_size;
|
||||
arena->flags = params->flags;
|
||||
|
||||
// Note(Ed): INLINED
|
||||
// internal void
|
||||
// arena_release(Arena *arena)
|
||||
// {
|
||||
// for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
// {
|
||||
// prev = n->prev;
|
||||
// os_release(n, n->res);
|
||||
// }
|
||||
// }
|
||||
asan_unpoison_memory_region(base, sizeof(Arena));
|
||||
return arena;
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop core functions
|
||||
|
||||
@@ -247,16 +148,16 @@ arena_pop(Arena *arena, U64 amt)
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
|
||||
internal Temp
|
||||
internal TempArena
|
||||
temp_begin(Arena *arena)
|
||||
{
|
||||
U64 pos = arena_pos(arena);
|
||||
Temp temp = {arena, pos};
|
||||
U64 pos = arena_pos(arena);
|
||||
TempArena temp = {arena, pos};
|
||||
return temp;
|
||||
}
|
||||
|
||||
internal void
|
||||
temp_end(Temp temp)
|
||||
temp_end(TempArena temp)
|
||||
{
|
||||
arena_pop_to(temp.arena, temp.pos);
|
||||
}
|
||||
|
||||
+14
-19
@@ -19,17 +19,19 @@
|
||||
typedef U32 ArenaFlags;
|
||||
enum
|
||||
{
|
||||
ArenaFlag_NoChain = ( 1 << 0),
|
||||
ArenaFlag_LargePages = ( 1 << 1),
|
||||
// Don't chain this arena
|
||||
ArenaFlag_NoChain = (1 << 0),
|
||||
// Only works if backing is virtual memory, will allocate a new backing VArena when the current block exhausts
|
||||
// Otherwise will assume backing can chain multiple block_size arenas until failure.
|
||||
ArenaFlag_ChainVirtual = (1 << 1),
|
||||
};
|
||||
|
||||
typedef struct ArenaParams ArenaParams;
|
||||
struct ArenaParams
|
||||
{
|
||||
ArenaFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
void* optional_backing_buffer;
|
||||
AllocatorInfo backing;
|
||||
ArenaFlags flags;
|
||||
U64 block_size; // If chaining VArenas set this to the reserve size
|
||||
};
|
||||
|
||||
/* NOTE(Ed): This is a combination of several concepts into a single interface:
|
||||
@@ -44,18 +46,14 @@ struct ArenaParams
|
||||
typedef struct Arena Arena;
|
||||
struct Arena
|
||||
{
|
||||
AllocatorInfo backing;
|
||||
Arena* prev; // previous arena in chain
|
||||
Arena* current; // current arena in chain
|
||||
ArenaFlags flags;
|
||||
U32 cmt_size;
|
||||
U64 res_size;
|
||||
U64 base_pos;
|
||||
AllocatorInfo backing;
|
||||
U64 pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
U64 block_size;
|
||||
ArenaFlags flags;
|
||||
};
|
||||
static_assert(sizeof(Arena) <= ARENA_HEADER_SIZE, "sizeof(Arena) <= MD_ARENA_HEADER_SIZE");
|
||||
static_assert(size_of(Arena) <= ARENA_HEADER_SIZE, "sizeof(Arena) <= ARENA_HEADER_SIZE");
|
||||
|
||||
typedef struct TempArena TempArena;
|
||||
struct TempArena
|
||||
@@ -67,12 +65,12 @@ struct TempArena
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
MD_API void* arena_allocator_proc(void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags);
|
||||
MD_API void* arena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags);
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
|
||||
MD_API Arena* arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_( & ( ArenaParams) { .reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__ } )
|
||||
#define arena_alloc(...) arena_alloc_( & ( ArenaParams) { .backing = {}, .reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__ } )
|
||||
|
||||
void arena_release(Arena *arena);
|
||||
|
||||
@@ -109,9 +107,6 @@ arena_release(Arena* arena)
|
||||
for (Arena* n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
{
|
||||
prev = n->prev;
|
||||
// os_release(n, n->res);
|
||||
alloc_free(arena->backing, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+7
-6
@@ -4,6 +4,7 @@
|
||||
# include "linkage.h"
|
||||
# include "macros.h"
|
||||
# include "platform.h"
|
||||
# include "base_types.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -200,19 +201,19 @@ void* mem_move( void* destination, void const* source, SSIZE byte_count )
|
||||
{
|
||||
if ( to_uptr(src_ptr) % size_of( SSIZE ) == to_uptr(dest_ptr) % size_of( SSIZE ) )
|
||||
{
|
||||
while ( pcast( UPTR, dest_ptr) % size_of( ssize ) )
|
||||
while ( pcast( UPTR, dest_ptr) % size_of( SSIZE ) )
|
||||
{
|
||||
if ( ! byte_count-- )
|
||||
return destination;
|
||||
|
||||
*dest_ptr++ = *src_ptr++;
|
||||
}
|
||||
while ( byte_count >= size_of( ssize ) )
|
||||
while ( byte_count >= size_of( SSIZE ) )
|
||||
{
|
||||
* rcast(SSIZE*, dest_ptr) = * rcast(SSIZE const*, src_ptr);
|
||||
byte_count -= size_of( ssize );
|
||||
dest_ptr += size_of( ssize );
|
||||
src_ptr += size_of( ssize );
|
||||
byte_count -= size_of( SSIZE );
|
||||
dest_ptr += size_of( SSIZE );
|
||||
src_ptr += size_of( SSIZE );
|
||||
}
|
||||
}
|
||||
for ( ; byte_count; byte_count-- )
|
||||
@@ -301,7 +302,7 @@ void* mem_set( void* destination, U8 fill_byte, SSIZE byte_count )
|
||||
byte_count -= align_offset;
|
||||
|
||||
{
|
||||
u64 fill_doubleword = ( scast( U64, fill_word) << 32 ) | fill_word;
|
||||
U64 fill_doubleword = ( scast( U64, fill_word) << 32 ) | fill_word;
|
||||
while ( byte_count > 31 )
|
||||
{
|
||||
* rcast( U64*, dest_ptr + 0 ) = fill_doubleword;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# include "../os/os.h"
|
||||
#endif
|
||||
|
||||
#ifdef MD_HEAP_ANALYSIS
|
||||
#define GEN_HEAP_STATS_MAGIC 0xDEADC0DE
|
||||
|
||||
typedef struct _heap_stats _heap_stats;
|
||||
@@ -47,8 +48,9 @@ struct _heap_alloc_info
|
||||
SSIZE size;
|
||||
void* physical_start;
|
||||
};
|
||||
#endif
|
||||
|
||||
void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags )
|
||||
void* heap_allocator_proc( void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags )
|
||||
{
|
||||
void* ptr = nullptr;
|
||||
// unused( allocator_data );
|
||||
@@ -62,7 +64,7 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSI
|
||||
ssize track_size = max( alloc_info_size, alignment ) + alloc_info_remainder;
|
||||
switch ( type )
|
||||
{
|
||||
case EAllocation_FREE :
|
||||
case EAllocatorMode_FREE :
|
||||
{
|
||||
if ( ! old_memory )
|
||||
break;
|
||||
@@ -72,7 +74,7 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSI
|
||||
old_memory = alloc_info->physical_start;
|
||||
}
|
||||
break;
|
||||
case EAllocation_ALLOC :
|
||||
case EAllocatorMode_ALLOC :
|
||||
{
|
||||
size += track_size;
|
||||
}
|
||||
@@ -82,76 +84,83 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSI
|
||||
}
|
||||
#endif
|
||||
|
||||
switch ( type )
|
||||
switch ( mode )
|
||||
{
|
||||
#if defined( COMPILER_MSVC ) || ( defined( COMPILER_GCC ) && defined( OS_WINDOWS ) ) || ( defined( COMPILER_TINYC ) && defined( OS_WINDOWS ) )
|
||||
case EAllocType_ALLOC :
|
||||
#if defined( COMPILER_MSVC ) || ( defined( COMPILER_GCC ) && defined( OS_WINDOWS ) ) || ( defined( COMPILER_TINYC ) && defined( OS_WINDOWS ) )
|
||||
case AllocatorMode_ALLOC:
|
||||
{
|
||||
ptr = _aligned_malloc( size, alignment );
|
||||
if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
zero_size( ptr, size );
|
||||
break;
|
||||
case EAllocType_FREE :
|
||||
}
|
||||
break;
|
||||
|
||||
case AllocatorMode_FREE:
|
||||
_aligned_free( old_memory );
|
||||
break;
|
||||
case EAllocType_RESIZE :
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
#elif defined( OS_LINUX ) && ! defined( CPU_ARM ) && ! defined( COMPILER_TINYC )
|
||||
case AllocatorMode_FREE_ALL:
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
|
||||
#elif defined( OS_LINUX ) && ! defined( CPU_ARM ) && ! defined( COMPILER_TINYC )
|
||||
case EAllocation_ALLOC :
|
||||
{
|
||||
ptr = aligned_alloc( alignment, ( size + alignment - 1 ) & ~( alignment - 1 ) );
|
||||
{
|
||||
ptr = aligned_alloc( alignment, ( size + alignment - 1 ) & ~( alignment - 1 ) );
|
||||
|
||||
if ( flags & GEN_ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
{
|
||||
zero_size( ptr, size );
|
||||
}
|
||||
if ( flags & GEN_ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
{
|
||||
zero_size( ptr, size );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EAllocation_FREE :
|
||||
{
|
||||
free( old_memory );
|
||||
}
|
||||
break;
|
||||
{
|
||||
free( old_memory );
|
||||
}
|
||||
break;
|
||||
|
||||
case EAllocation_RESIZE :
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
#else
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case EAllocType_ALLOC :
|
||||
{
|
||||
posix_memalign( &ptr, alignment, size );
|
||||
{
|
||||
posix_memalign( &ptr, alignment, size );
|
||||
|
||||
if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
{
|
||||
zero_size( ptr, size );
|
||||
}
|
||||
if ( flags & ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
{
|
||||
zero_size( ptr, size );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case EAllocType_FREE :
|
||||
{
|
||||
free( old_memory );
|
||||
}
|
||||
break;
|
||||
{
|
||||
free( old_memory );
|
||||
}
|
||||
break;
|
||||
|
||||
case EAllocType_RESIZE :
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
{
|
||||
AllocatorInfo a = heap();
|
||||
ptr = default_resize_align( a, old_memory, old_size, size, alignment );
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EAllocType_FREE_ALL :
|
||||
case AllocatorMode_FREE_ALL:
|
||||
break;
|
||||
|
||||
case AllocatorMode_QueryType:
|
||||
return (void*) Heap
|
||||
}
|
||||
|
||||
#ifdef GEN_HEAP_ANALYSIS
|
||||
@@ -172,6 +181,44 @@ void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSI
|
||||
|
||||
void* vm_allocator_proc(void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags)
|
||||
{
|
||||
void* result = nullptr;
|
||||
|
||||
// if(params->flags & ArenaFlag_LargePages)
|
||||
// {
|
||||
// base = os_reserve_large(reserve_size);
|
||||
// os_commit_large(base, commit_size);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// base = os_reserve(reserve_size);
|
||||
// os_commit(base, commit_size);
|
||||
// }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VMemory vm_alloc(VMemoryParams params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = align_pow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = align_pow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = align_pow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = align_pow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
|
||||
// Allocate virtual memory
|
||||
is_virtual = true;
|
||||
|
||||
VMemory vm = ;
|
||||
|
||||
// TODO(Ed): Move this to vmem?
|
||||
asan_poison_memory_region(base, params->commit_size);
|
||||
}
|
||||
|
||||
@@ -19,18 +19,29 @@
|
||||
#define MD__HAS_ZERO( x ) ( ( ( x ) - MD__ONES ) & ~( x ) & MD__HIGHS )
|
||||
#endif
|
||||
|
||||
typedef U32 AllocType;
|
||||
enum AllocType enum_underlying(U32)
|
||||
// Return value of allocator_type
|
||||
typedef U32 AllocatorType;
|
||||
enum
|
||||
{
|
||||
EAllocType_ALLOC,
|
||||
EAllocType_FREE,
|
||||
EAllocType_FREE_ALL,
|
||||
EAllocType_RESIZE,
|
||||
AllocatorType_Heap = 0, // Genreal heap allocator
|
||||
AllocatorType_VArena = 1, // Arena allocator backed by virtual address space
|
||||
AllocatorType_FArena = 2, // Fixed arena backed back by a fixed size block of memory (usually a byte slice)
|
||||
AllocatorType_Arena = 3, // Composite arena used originally by RAD Debugger & Metadesk
|
||||
};
|
||||
|
||||
typedef void*(AllocatorProc)( void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags );
|
||||
typedef U32 AllocatorMode;
|
||||
enum AllocatorMode enum_underlying(U32)
|
||||
{
|
||||
AllocatorMode_ALLOC,
|
||||
AllocatorMode_FREE,
|
||||
AllocatorMode_FREE_ALL,
|
||||
AllocatorMode_RESIZE,
|
||||
AllocatorMode_QueryType,
|
||||
};
|
||||
|
||||
typedef struct AllocatorInfo;
|
||||
typedef void*(AllocatorProc)( void* allocator_data, AllocatorMode type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags );
|
||||
|
||||
typedef struct AllocatorInfo AllocatorInfo;
|
||||
struct AllocatorInfo
|
||||
{
|
||||
AllocatorProc* proc;
|
||||
@@ -50,6 +61,9 @@ enum AllocFlag
|
||||
# define MD_DEFAULT_ALLOCATOR_FLAGS ( ALLOCATOR_FLAG_CLEAR_TO_ZERO )
|
||||
#endif
|
||||
|
||||
// Allows the user to retrieve which type of allocator is being used.
|
||||
AllocatorType allocator_type(AllocatorInfo a);
|
||||
|
||||
//! Allocate memory with default alignment.
|
||||
void* alloc( AllocatorInfo a, SSIZE size );
|
||||
|
||||
@@ -83,6 +97,7 @@ void* resize_align( AllocatorInfo a, void* ptr, SSIZE old_size, SSIZE new_size,
|
||||
//! Use this if you don't need a "fancy" resize allocation
|
||||
void* default_resize_align( AllocatorInfo a, void* ptr, SSIZE old_size, SSIZE new_size, SSIZE alignment );
|
||||
|
||||
#ifdef MD_HEAP_ANALYSIS
|
||||
/* heap memory analysis tools */
|
||||
/* define GEN_HEAP_ANALYSIS to enable this feature */
|
||||
/* call zpl_heap_stats_init at the beginning of the entry point */
|
||||
@@ -91,8 +106,9 @@ MD_API void heap_stats_init( void );
|
||||
MD_API SSIZE heap_stats_used_memory( void );
|
||||
MD_API SSIZE heap_stats_alloc_count( void );
|
||||
MD_API void heap_stats_check( void );
|
||||
#endif
|
||||
|
||||
MD_API void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags );
|
||||
MD_API void* heap_allocator_proc( void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags );
|
||||
|
||||
#ifndef heap
|
||||
//! The heap allocator backed by operating system's memory manager.
|
||||
@@ -109,44 +125,83 @@ MD_API void* heap_allocator_proc( void* allocator_data, AllocType type, SSIZE si
|
||||
#define mfree( ptr ) free( heap(), ptr )
|
||||
#endif
|
||||
|
||||
typedef U32 VMemoryFlags;
|
||||
/* Virtual Memory Arena
|
||||
This is separate from the composite arena used by HMH/Casey Muratori/RJF
|
||||
This arena stricly manages one reservation of the process's virtual address space.
|
||||
|
||||
Segregating this from composite Arena style causes more moremoy to be used for "allocator headers", however it allows
|
||||
users of a library to have greater control over the allocation strategy used from their side instead of the library itself.
|
||||
|
||||
Like with the composite Arena, the VArena has its struct as the header of the reserve of memory.
|
||||
*/
|
||||
|
||||
typedef U32 VArenaFlags;
|
||||
enum
|
||||
{
|
||||
VMemoryFlag_NoChain = (1 << 0),
|
||||
VMemoryFlag_LargePages = (1 << 1),
|
||||
VArenaFlag_LargePages = (1 << 0),
|
||||
};
|
||||
|
||||
typedef struct VMemory_Params;
|
||||
struct VMemory_Params
|
||||
typedef struct VArenaParams VArenaParams;
|
||||
struct VArenaParams
|
||||
{
|
||||
VMemoryFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
// void* optional_backing_buffer;
|
||||
U64 base_addr;
|
||||
VArenaFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
};
|
||||
|
||||
typedef struct VMemory;
|
||||
struct VMemory
|
||||
typedef struct VArena VArena;
|
||||
struct VArena
|
||||
{
|
||||
U32 cmt_size;
|
||||
U32 res_size;
|
||||
VArenaFlags flags;
|
||||
U64 base_pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
U64 res_size;
|
||||
U64 cmt_size;
|
||||
};
|
||||
|
||||
AllocatorInfo vm_allocator(VMemory* vm) {
|
||||
AllocatorInfo info = { vm_allocator_proc, vm }
|
||||
return info
|
||||
AllocatorInfo vm_allocator(VArena* vm) {
|
||||
AllocatorInfo info = { vm_allocator_proc, vm };
|
||||
return info;
|
||||
}
|
||||
|
||||
MD_API void* vm_allocator_proc(void* allocator_data, AllocType type, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags);
|
||||
VArena* varena_alloc (VArenaParams params);
|
||||
void varena_commit (VArena vm, SSIZE commit_size);
|
||||
VArenaParams varena_free (VArena vm);
|
||||
SSIZE varena_page_size(SSIZE* alignment_out);
|
||||
|
||||
MD_API void* varena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags);
|
||||
|
||||
typedef struct ByteSlice ByteSlice;
|
||||
struct ByteSlice
|
||||
{
|
||||
U8* data;
|
||||
SSIZE len;
|
||||
};
|
||||
|
||||
// Fixed size arena
|
||||
typedef struct FArena FArena;
|
||||
struct FArena
|
||||
{
|
||||
ByteSlice slice;
|
||||
SSIZE pos;
|
||||
};
|
||||
|
||||
FArena farena_from_byteslice(ByteSlice slice);
|
||||
|
||||
MD_API void* farena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, SSIZE alignment, void* old_memory, SSIZE old_size, U64 flags);
|
||||
|
||||
// Inlines
|
||||
|
||||
inline
|
||||
AllocatorType allocator_type(AllocatorInfo a) {
|
||||
return (AllocatorType) a.proc(a.data, AllocatorMode_QueryType, 0, 0, nullptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS);
|
||||
}
|
||||
|
||||
inline
|
||||
void* alloc_align( AllocatorInfo a, SSIZE size, SSIZE alignment ) {
|
||||
return a.Proc( a.Data, EAllocType_ALLOC, size, alignment, nullptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
return a.proc( a.data, AllocatorMode_ALLOC, size, alignment, nullptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -157,12 +212,12 @@ void* alloc( AllocatorInfo a, SSIZE size ) {
|
||||
inline
|
||||
void allocator_free( AllocatorInfo a, void* ptr ) {
|
||||
if ( ptr != nullptr )
|
||||
a.Proc( a.Data, EAllocType_FREE, 0, 0, ptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
a.proc( a.data, AllocatorMode_FREE, 0, 0, ptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
}
|
||||
|
||||
inline
|
||||
void free_all( AllocatorInfo a ) {
|
||||
a.Proc( a.Data, EAllocType_FREE_ALL, 0, 0, nullptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
a.proc( a.data, AllocatorMode_FREE_ALL, 0, 0, nullptr, 0, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
}
|
||||
|
||||
inline
|
||||
@@ -172,7 +227,7 @@ void* resize( AllocatorInfo a, void* ptr, SSIZE old_size, SSIZE new_size ) {
|
||||
|
||||
inline
|
||||
void* resize_align( AllocatorInfo a, void* ptr, SSIZE old_size, SSIZE new_size, SSIZE alignment ) {
|
||||
return a.Proc( a.Data, EAllocType_RESIZE, new_size, alignment, ptr, old_size, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
return a.proc( a.data, AllocatorMode_RESIZE, new_size, alignment, ptr, old_size, MD_DEFAULT_ALLOCATOR_FLAGS );
|
||||
}
|
||||
|
||||
inline
|
||||
|
||||
@@ -36,4 +36,3 @@ MD_NS_END
|
||||
|
||||
// metagen
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user