From d937a99b51dbf18b0e6423ee0cd9bb8368b69426 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Tue, 20 Jul 2021 21:23:14 -0700 Subject: [PATCH] implementation of arena constructed on reserve/commit/decommit/release --- source/md.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++++---- source/md.h | 30 ++++---- 2 files changed, 193 insertions(+), 29 deletions(-) diff --git a/source/md.c b/source/md.c index de99ed3..5145911 100644 --- a/source/md.c +++ b/source/md.c @@ -1,8 +1,17 @@ // LICENSE AT END OF FILE (MIT). // NOTE(allen): Notes on overrides/macro options: -// #define MD_IMPL_FileIterIncrement -> override default implementation -// #define MD_NO_DEFAULT_IMPL -> skip OS specific code for implementation +// Individual Overridables: +// #define MD_IMPL_FileIterIncrement +// #define MD_IMPL_Alloc +// #define MD_IMPL_Reserve +// #define MD_IMPL_Commit +// #define MD_IMPL_Decommit +// #define MD_IMPL_Release +// #define MD_IMPL_ArenaNew +// #define MD_IMPL_ArenaRelease +// Default Implementation Controls +// #define MD_NO_DEFAULT_IMPL -> skip code for all default implementations #if !defined(MD_NO_DEFAULT_IMPL) # define MD_NO_DEFAULT_IMPL 0 @@ -79,6 +88,40 @@ MD_WIN32_FileIterIncrement(MD_FileIter *it, MD_String8 path, MD_FileInfo *out_in return result; } +#if !defined(MD_IMPL_Reserve) +# define MD_IMPL_Reserve MD_WIN32_Reserve +#endif +#if !defined(MD_IMPL_Commit) +# define MD_IMPL_Commit MD_WIN32_Commit +#endif +#if !defined(MD_IMPL_Decommit) +# define MD_IMPL_Decommit MD_WIN32_Decommit +#endif +#if !defined(MD_IMPL_Release) +# define MD_IMPL_Release MD_WIN32_Release +#endif + +static void* +MD_WIN32_Reserve(MD_u64 size){ + void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE); + return(result); +} + +static void +MD_WIN32_Commit(void *ptr, MD_u64 size){ + VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE); +} + +static void +MD_WIN32_Decommit(void *ptr, MD_u64 size){ + VirtualFree(ptr, size, MEM_DECOMMIT); +} + +static void +MD_WIN32_Release(void *ptr, MD_u64 size){ + VirtualFree(ptr, 0, MEM_RELEASE); +} + #endif //~///////////////////////////////////////////////////////////////////////////// @@ -163,14 +206,123 @@ MD_LINUX_FileIterIncrement(MD_FileIter *opaque_it, MD_String8 path, MD_FileInfo #endif +//~///////////////////////////////////////////////////////////////////////////// +///////////// MD Arena From Reserve/Commit/Decommit/Release //////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#define MD_ArenaDefault_HeaderSize 64 +#define MD_ArenaDefault_CommitSize (1 << 20) + +typedef struct MD_ArenaDefault MD_ArenaDefault; +struct MD_ArenaDefault{ + MD_ArenaFunc *func; + MD_u64 pos; + MD_u64 cmt; + MD_u64 cap; + MD_u64 align; +}; +MD_StaticAssert(sizeof(MD_ArenaDefault) <= MD_ArenaDefault_HeaderSize, arena_def_size_check); + +#define MD_IMPL_ArenaNew MD_ArenaDefaultNew +#define MD_IMPL_ArenaRelease MD_ArenaDefaultRelease + +static MD_IntPtr +MD_ArenaDefaultImpl(MD_Arena *arena_opq, MD_ArenaOperation op, MD_u64 v){ + MD_ArenaDefault *arena = (MD_ArenaDefault*)arena_opq; + MD_u8 *buf = (MD_u8*)arena_opq; + MD_IntPtr result = MD_ZERO_STRUCT; + switch (op){ + case MD_ArenaOperation_GetPos: + { + result.u64 = arena->pos; + }break; + + case MD_ArenaOperation_GetCap: + { + result.u64 = arena->cap; + }break; + + case MD_ArenaOperation_Push: + { + if (arena->pos + v <= arena->cap){ + MD_u64 pos = arena->pos; + MD_u64 pos_clamped = ((pos > MD_ArenaDefault_HeaderSize) ? pos : MD_ArenaDefault_HeaderSize); + MD_u64 new_pos = pos_clamped + v; + MD_u64 align_m1 = arena->align - 1; + MD_u64 new_pos_aligned = (new_pos + align_m1)&(~align_m1); + MD_u64 new_pos_clamped = ((arena->cap < new_pos_aligned) ? arena->cap : new_pos_aligned); + result.ptr = buf + pos; + arena->pos = new_pos_aligned; + + if (new_pos_clamped > arena->cmt){ + MD_u64 cmt_amt_raw = new_pos_clamped - arena->cmt; + MD_u64 cmt_align_m1 = MD_ArenaDefault_CommitSize - 1; + MD_u64 cmt_amt = (cmt_amt_raw + cmt_align_m1)&(~cmt_align_m1); + MD_IMPL_Commit(buf + arena->cmt, cmt_amt); + arena->cmt += cmt_amt; + } + } + }break; + + case MD_ArenaOperation_PopTo: + { + MD_u64 pos_clamped = ((v > MD_ArenaDefault_HeaderSize) ? v : MD_ArenaDefault_HeaderSize); + arena->pos = pos_clamped; + }break; + + case MD_ArenaOperation_PushAlign: + { + MD_u64 pos = arena->pos; + MD_u64 pos_clamped = ((pos > MD_ArenaDefault_HeaderSize) ? pos : MD_ArenaDefault_HeaderSize); + MD_u64 align_m1 = arena->align - 1; + MD_u64 new_pos_aligned = (pos_clamped + align_m1)&(~align_m1); + MD_u64 new_pos_clamped = ((arena->cap < new_pos_aligned) ? arena->cap : new_pos_aligned); + arena->pos = new_pos_clamped; + }break; + + case MD_ArenaOperation_SetAutoAlign: + { + arena->align = v; + }break; + } + return(result); +} + +static MD_Arena* +MD_ArenaDefaultNew(MD_u64 cap){ + void *mem = MD_IMPL_Reserve(cap); + MD_u64 cmt = ((MD_ArenaDefault_CommitSize < cap) ? MD_ArenaDefault_CommitSize : cap); + MD_IMPL_Commit(mem, cmt); + + MD_ArenaDefault *arena = (MD_ArenaDefault*)mem; + arena->func = MD_ArenaDefaultImpl; + arena->pos = MD_ArenaDefault_HeaderSize; + arena->cmt = cmt; + arena->cap = cap; + arena->align = sizeof(void*); + return((MD_Arena*)arena); +} + +static void +MD_ArenaDefaultRelease(MD_Arena *arena_opq){ + MD_ArenaDefault *arena = (MD_ArenaDefault*)arena_opq; + MD_u64 cap = arena->cap; + MD_IMPL_Release(arena, cap); +} + //~///////////////////////////////////////////////////////////////////////////// //////////////////////// MD Library Implementation ///////////////////////////// //////////////////////////////////////////////////////////////////////////////// -#if !defined(MD_IMPL_FileIterIncrement) -# error Missing implementation for MD_IMPL_FileIterIncrement +#if !defined(MD_IMPL_Alloc) +# error Missing implementation for MD_IMPL_Alloc +#endif +#if !defined(MD_IMPL_ArenaNew) +# error Missing implementation for MD_IMPL_ArenaNew +#endif +#if !defined(MD_IMPL_ArenaRelease) +# error Missing implementation for MD_IMPL_ArenaRelease #endif - #define MD_FUNCTION_IMPL MD_FUNCTION #define MD_PRIVATE_FUNCTION_IMPL MD_FUNCTION_IMPL @@ -205,16 +357,18 @@ static MD_Node _md_nil_node = //~ Memory Operations -MD_FUNCTION_IMPL void +MD_FUNCTION_IMPL void* MD_MemoryZero(void *memory, MD_u64 size) { memset(memory, 0, size); + return(memory); } -MD_FUNCTION_IMPL void +MD_FUNCTION_IMPL void* MD_MemoryCopy(void *dest, void *src, MD_u64 size) { memcpy(dest, src, size); + return(dest); } MD_FUNCTION_IMPL void * @@ -232,15 +386,13 @@ MD_AllocZero(MD_u64 size) //~ Arena Functions MD_FUNCTION void* -MD_ArenaPush(MD_Arena *arena, MD_u64 v) -{ +MD_ArenaPush(MD_Arena *arena, MD_u64 v){ MD_IntPtr result = arena->func(arena, MD_ArenaOperation_Push, v); return(result.ptr); } MD_FUNCTION MD_ArenaTemp -MD_ArenaBeginTemp(MD_Arena *arena) -{ +MD_ArenaBeginTemp(MD_Arena *arena){ MD_IntPtr pos = arena->func(arena, MD_ArenaOperation_GetPos, 0); MD_ArenaTemp result = MD_ZERO_STRUCT; result.arena = arena; @@ -249,8 +401,7 @@ MD_ArenaBeginTemp(MD_Arena *arena) } MD_FUNCTION void -MD_ArenaEndTemp(MD_ArenaTemp temp) -{ +MD_ArenaEndTemp(MD_ArenaTemp temp){ temp.arena->func(temp.arena, MD_ArenaOperation_PopTo, temp.pos); } @@ -264,6 +415,21 @@ MD_ArenaPushAlign(MD_Arena *arena, MD_u64 v){ arena->func(arena, MD_ArenaOperation_PushAlign, v); } +MD_FUNCTION void +MD_ArenaClear(MD_Arena *arena){ + arena->func(arena, MD_ArenaOperation_PopTo, 0); +} + +MD_FUNCTION MD_Arena* +MD_ArenaNew(MD_u64 cap){ + return(MD_IMPL_ArenaNew(cap)); +} + +MD_FUNCTION void +MD_ArenaRelease(MD_Arena *arena){ + MD_IMPL_ArenaRelease(arena); +} + //~ Characters diff --git a/source/md.h b/source/md.h index 06dd44c..8c6d8c0 100644 --- a/source/md.h +++ b/source/md.h @@ -1,11 +1,6 @@ -//~ Metadesk Library // LICENSE AT END OF FILE (MIT). -// NOTE(allen): "Plugin" functionality -// -// MD_b32 MD_IMPL_FileIterIncrement(MD_FileIter*, MD_String8, MD_FileInfo*) - optional -// void* MD_IMPL_Alloc(MD_u64) - required -// +//~ Metadesk Library #ifndef MD_H #define MD_H @@ -260,15 +255,14 @@ typedef double MD_f64; //~ Abstract Arena typedef union MD_IntPtr MD_IntPtr; -union MD_IntPtr -{ +union MD_IntPtr{ MD_u64 u64; void *ptr; }; -typedef enum MD_ArenaOperation -{ +typedef enum MD_ArenaOperation{ MD_ArenaOperation_GetPos, + MD_ArenaOperation_GetCap, MD_ArenaOperation_Push, MD_ArenaOperation_PopTo, MD_ArenaOperation_PushAlign, @@ -278,16 +272,14 @@ typedef enum MD_ArenaOperation typedef MD_IntPtr MD_ArenaFunc(struct MD_Arena *arena, MD_ArenaOperation op, MD_u64 v); typedef struct MD_Arena MD_Arena; -struct MD_Arena -{ +struct MD_Arena{ MD_ArenaFunc *func; }; //~ Arena Helpers typedef struct MD_ArenaTemp MD_ArenaTemp; -struct MD_ArenaTemp -{ +struct MD_ArenaTemp{ MD_Arena *arena; MD_u64 pos; }; @@ -692,8 +684,8 @@ struct MD_FileIter //~ Memory Operations -MD_FUNCTION void MD_MemoryZero(void *memory, MD_u64 size); -MD_FUNCTION void MD_MemoryCopy(void *dst, void *src, MD_u64 size); +MD_FUNCTION void* MD_MemoryZero(void *memory, MD_u64 size); +MD_FUNCTION void* MD_MemoryCopy(void *dst, void *src, MD_u64 size); MD_FUNCTION void* MD_AllocZero(MD_u64 size); #define MD_PushArray(T,c) (T*)MD_AllocZero(sizeof(T)*(c)) @@ -710,8 +702,14 @@ MD_FUNCTION MD_ArenaTemp MD_ArenaBeginTemp(MD_Arena *arena); MD_FUNCTION void MD_ArenaEndTemp(MD_ArenaTemp temp); MD_FUNCTION void MD_ArenaSetAlign(MD_Arena *arena, MD_u64 v); MD_FUNCTION void MD_ArenaPushAlign(MD_Arena *arena, MD_u64 v); +MD_FUNCTION void MD_ArenaClear(MD_Arena *arena); #define MD_PushArrayAr(a,T,c) (T*)(MD_ArenaPush((a), sizeof(T)*(c))) +#define MD_PushArrayZeroAr(a,T,c) (T*)(MD_MemoryZero(MD_ArenaPush((a), sizeof(T)*(c)),\ +sizeof(T)*(c))) + +MD_FUNCTION MD_Arena* MD_ArenaNew(MD_u64 cap); +MD_FUNCTION void MD_ArenaRelease(MD_Arena *arena); //~ Characters