diff --git a/bin/build.ps1 b/bin/build.ps1 index 980b663..2420bd9 100644 --- a/bin/build.ps1 +++ b/bin/build.ps1 @@ -39,8 +39,9 @@ write-host "Core Count - Physical: $CoreCount_Physical Logical: $CoreCount_Logic #region Arguments $vendor = $null $release = $null -[bool] $verbose = $false -[bool] $code_sanity = $false +[bool] $verbose = $false +[bool] $code_sanity = $false +[bool] $compile_sanity = $false [array] $vendors = @( "clang", "msvc" ) @@ -48,11 +49,12 @@ $release = $null if ( $args ) { $args | ForEach-Object { switch ($_) { - { $_ -in $vendors } { $vendor = $_; break } - "verbose" { $verbose = $true } - "release" { $release = $true } - "debug" { $release = $false } - "code_sanity" { $code_sanity = $true } + { $_ -in $vendors } { $vendor = $_; break } + "verbose" { $verbose = $true } + "release" { $release = $true } + "debug" { $release = $false } + "code_sanity" { $code_sanity = $true } + "compile_sanity" { $compile_sanity = $true } } } } @@ -79,7 +81,8 @@ else { $optimize = $true } -$cannot_build = $code_snaity -eq $false +$cannot_build = $code_sanity -eq $false +$cannot_build = $cannot_build -and $compile_sanity -eq $false if ( $cannot_build ) { throw "No build target specified. One must be specified, this script will not assume one" } @@ -98,7 +101,7 @@ $path_third_party = join-path $path_root third_party verify-path $path_build -if ($code_sanity) +if ($compile_sanity) { write-host "Building code/metadesk.c (sanity compile) with $vendor" @@ -119,4 +122,25 @@ if ($code_sanity) $result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable } +if ($code_sanity) +{ + write-host "Building test/code_sanity.c" + + $compiler_args = @() + $compiler_args += $flag_all_c + $compiler_args += $flag_updated_cpp_macro + $compiler_args += $flag_c11 + + $linker_args = @() + $linker_args += $flag_link_win_subsystem_console + + $path_base = join-path $path_code base + + $includes = @( $path_base ) + $unit = join-path $path_code 'metadesk.c' + $executable = join-path $path_build 'metadesk.lib' + + $result = build-simple $path_build $includes $compiler_args $linker_args $unit $executable +} + Pop-Location # $path_root diff --git a/code/base/arena.c b/code/base/arena.c index fe98cf6..beab611 100644 --- a/code/base/arena.c +++ b/code/base/arena.c @@ -181,4 +181,6 @@ void* arena_allocator_proc(void* allocator_data, AllocatorMode mode, SSIZE size, } break; } + + return allocated_ptr; } diff --git a/code/base/arena.h b/code/base/arena.h index 6912095..6559cc0 100644 --- a/code/base/arena.h +++ b/code/base/arena.h @@ -139,7 +139,7 @@ arena_pop(Arena* arena, SSIZE amt) { //- rjf: temporary arena scopes inline TempArena -temp_begin(Arena *arena) { +temp_begin(Arena* arena) { U64 pos = arena_pos(arena); TempArena temp = {arena, pos}; return temp; diff --git a/code/base/logger.h b/code/base/logger.h index 1bdd7f4..c597742 100644 --- a/code/base/logger.h +++ b/code/base/logger.h @@ -48,6 +48,8 @@ struct Log //////////////////////////////// //~ rjf: Log Creation/Selection + + Log* log_alloc(AllocatorInfo ainfo, U64 arena_block_size); void log_release(Log* log); MD_API void log_select (Log* log); @@ -82,5 +84,5 @@ MD_API void log_msgf(LogMsgKind kind, char* fmt, ...); //////////////////////////////// //~ rjf: Log Scopes -MD_API void log_scope_begin(void); + void log_scope_begin(void); MD_API LogScopeResult log_scope_end(Arena* arena); diff --git a/code/base/memory_substrate.c b/code/base/memory_substrate.c index adfd44f..297b79e 100644 --- a/code/base/memory_substrate.c +++ b/code/base/memory_substrate.c @@ -242,6 +242,7 @@ varena__alloc(VArenaParams params) vm->committed = commit_size; vm->commit_used = 0; vm->flags = params.flags; + return vm; } void diff --git a/code/base/strings.c b/code/base/strings.c index 77037e0..d59c709 100644 --- a/code/base/strings.c +++ b/code/base/strings.c @@ -2016,10 +2016,7 @@ fuzzy_match_find(Arena *arena, String8 needle, String8 haystack) FuzzyMatchRangeList fuzzy_match_find_alloc(AllocatorInfo ainfo, String8 needle, String8 haystack) { - // TODO(Ed): Review, we should just keep using thread scratch arenas (and provide them to teh context) - Arena* arena = arena_alloc(.backing = ainfo, .block_size = MB(1)); - TempArena scratch = temp_begin(&arena, 1); - + TempArena scratch = scratch_begin(0, 0); String8List needles = str8_split(scratch.arena, needle, (U8*)" ", 1, 0); FuzzyMatchRangeList result = {0}; @@ -2045,7 +2042,7 @@ fuzzy_match_find_alloc(AllocatorInfo ainfo, String8 needle, String8 haystack) } if (find_pos < haystack.size) { Rng1U64 range = r1u64(find_pos, find_pos+needle_n->string.size); - FuzzyMatchRangeNode* n = push_array(arena, FuzzyMatchRangeNode, 1); + FuzzyMatchRangeNode* n = push_array(scratch.arena, FuzzyMatchRangeNode, 1); n->range = range; sll_queue_push(result.first, result.last, n); result.count += 1; @@ -2053,7 +2050,6 @@ fuzzy_match_find_alloc(AllocatorInfo ainfo, String8 needle, String8 haystack) } } temp_end(scratch); - arena_release(arena); return result; } @@ -2239,7 +2235,7 @@ str8_serial_alloc_u64(AllocatorInfo ainfo, String8List* srl, U64 x) { } void -str8_serial_push_u32(AllocatorInfo ainfo, String8List* srl, U32 x) { +str8_serial_alloc_u32(AllocatorInfo ainfo, String8List* srl, U32 x) { U8* buf = alloc_array_no_zero(ainfo, U8, 4); memory_copy(buf, &x, 4); String8 *str = &srl->last->string; diff --git a/code/base/thread_context.c b/code/base/thread_context.c index fc4b2e8..04fb2bd 100644 --- a/code/base/thread_context.c +++ b/code/base/thread_context.c @@ -16,24 +16,34 @@ MD_API_C thread_static TCTX* tctx_thread_local = 0; #endif void -tctx_init_and_equip(TCTX* tctx){ +tctx_init_and_equip(TCTX* tctx) +{ memory_zero_struct(tctx); + Arena** arena_ptr = tctx->arenas; - for (U64 i = 0; i < array_count(tctx->arenas); i += 1, arena_ptr += 1) { - // TODO(Ed): Review this, we are not exposing a way for the user to defining the backing of these thread-context arenas. - VArena* vm = varena_alloc(.reserve_size = VARENA_DEFAULT_RESERVE, .commit_size = VARENA_DEFAULT_COMMIT); - *arena_ptr = arena_alloc(.backing = varena_allocator(vm)); + for (U64 i = 0; i < array_count(tctx->arenas); i += 1, arena_ptr += 1) + { + if (*arena_ptr == nullptr) + { + VArena* vm = varena_alloc(.reserve_size = VARENA_DEFAULT_RESERVE, .commit_size = VARENA_DEFAULT_COMMIT); + *arena_ptr = arena_alloc(.backing = varena_allocator(vm)); + } } tctx_thread_local = tctx; } void -tctx_init_and_equip_ainfos(TCTX* tctx, AllocatorInfo ainfos[2]) { +tctx_init_and_equip_alloc(TCTX* tctx, AllocatorInfo ainfo) +{ memory_zero_struct(tctx); + Arena** arena_ptr = tctx->arenas; - for (U64 i = 0; i < array_count(tctx->arenas); i += 1, arena_ptr += 1) { - // TODO(Ed): Is this ok? Is it alright that the thread context can use Arenas? - *arena_ptr = arena_alloc(.backing = ainfos[i]); + for (U64 i = 0; i < array_count(tctx->arenas); i += 1, arena_ptr += 1) + { + if (*arena_ptr == nullptr) + { + *arena_ptr = arena_alloc(.backing = ainfo); + } } tctx_thread_local = tctx; } diff --git a/code/base/thread_context.h b/code/base/thread_context.h index d977579..ebdcdeb 100644 --- a/code/base/thread_context.h +++ b/code/base/thread_context.h @@ -25,10 +25,10 @@ struct TCTX //////////////////////////////// // NOTE(allen): Thread Context Functions -MD_API void tctx_init_and_equip(TCTX* tctx); -MD_API void tctx_init_and_equip_ainfos(TCTX* tctx, AllocatorInfo ainfos[2]); -MD_API void tctx_release(void); -MD_API TCTX* tctx_get_equipped(void); +MD_API void tctx_init_and_equip (TCTX* tctx); +MD_API void tctx_init_and_equip_alloc(TCTX* tctx, AllocatorInfo ainfo); +MD_API void tctx_release (void); +MD_API TCTX* tctx_get_equipped (void); MD_API Arena* tctx_get_scratch(Arena** conflicts, U64 count); diff --git a/code/mdesk/mdesk.c b/code/mdesk/mdesk.c index 3906dc3..e7c712b 100644 --- a/code/mdesk/mdesk.c +++ b/code/mdesk/mdesk.c @@ -5,6 +5,24 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +// Context + +void init(Context* ctx) +{ + if (ctx->backing[0].proc != nullptr) { + tctx_init_and_equip_alloc(& ctx->thread_ctx, ctx->backing[0]); + } + else { + tctx_init_and_equip(& ctx->thread_ctx); + } +} + +void deinit(Context* ctx) +{ + tctx_release(); +} + //////////////////////////////// //~ rjf: Message Type Functions diff --git a/code/mdesk/mdesk.h b/code/mdesk/mdesk.h index 4cc2796..ac40bbc 100644 --- a/code/mdesk/mdesk.h +++ b/code/mdesk/mdesk.h @@ -221,6 +221,22 @@ struct ParseResult MsgList msgs; }; +//////////////////////////////// +// Context + +typedef struct Context Context; +struct Context +{ + // Note: Only used so far as the first fallback if the user did not preset the thread_context's arenas + // Otherwise it will just reserve its own Arena backed by chained virutal address space + AllocatorInfo backing[2]; + + // Its recommended that the user hooks up + // their own arena allocators to the thread context + // which will be utilized for thread local scratch arena + TCTX thread_ctx; +}; + //////////////////////////////// //~ rjf: Globals @@ -241,6 +257,12 @@ nil_node() return &nil; } +//////////////////////////////// +// Context lifetime Functios + +MD_API void init (Context* ctx); +MD_API void deinit(Context* ctx); + //////////////////////////////// //~ rjf: Message Type Functions diff --git a/code/metadesk.c b/code/metadesk.c index 0167769..125b792 100644 --- a/code/metadesk.c +++ b/code/metadesk.c @@ -27,4 +27,5 @@ MD_NS_BEGIN #include "os/os.c" #include "mdesk/mdesk.c" + MD_NS_END diff --git a/code/os/os.c b/code/os/os.c index b765f30..116fb69 100644 --- a/code/os/os.c +++ b/code/os/os.c @@ -86,7 +86,7 @@ os_string_from_file_range_alloc(AllocatorInfo ainfo, OS_Handle file, Rng1U64 ran // TODO(Ed): It may be better to actually wrap the alloation in an arena and then rewind it. // This would ensure resize isn't doing an expensive shrink (from a bad heap realloc, or something else) // That or we just leave it up to the user to make sure to pass in an arena. - resize(ainfo, result.str, result.size, result.str + actual_read_size); + resize(ainfo, result.str, result.size, scast(U64, result.str) + actual_read_size); result.size = actual_read_size; } return result; diff --git a/code/os/win32/os_win32.c b/code/os/win32/os_win32.c index 719f176..928a160 100644 --- a/code/os/win32/os_win32.c +++ b/code/os/win32/os_win32.c @@ -6,7 +6,7 @@ // Copyright (c) 2024 Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) -MD_API_C global OS_W32_State os_w32_state = {0}; +MD_API global OS_W32_State os_w32_state = {0}; //////////////////////////////// //~ rjf: Modern Windows SDK Functions @@ -14,7 +14,7 @@ MD_API_C global OS_W32_State os_w32_state = {0}; // (We must dynamically link to them, since they can be missing in older SDKs) typedef HRESULT W32_SetThreadDescription_Type(HANDLE hThread, PCWSTR lpThreadDescription); -MD_API_C global W32_SetThreadDescription_Type* w32_SetThreadDescription_func = 0; +MD_API global W32_SetThreadDescription_Type* w32_SetThreadDescription_func = 0; //////////////////////////////// //~ rjf: Time Conversion Helpers @@ -867,7 +867,7 @@ B32 os_thread_join(OS_Handle handle, U64 endt_us) { DWORD sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(handle.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(handle.u64[0]); DWORD wait_result = WAIT_OBJECT_0; if (entity != 0) { wait_result = WaitForSingleObject(entity->thread.handle, sleep_ms); @@ -878,7 +878,7 @@ os_thread_join(OS_Handle handle, U64 endt_us) void os_thread_detach(OS_Handle thread) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(thread.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(thread.u64[0]); os_w32_entity_release(entity); } @@ -897,20 +897,20 @@ os_mutex_alloc(void) { void os_mutex_release(OS_Handle mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(mutex.u64[0]); os_w32_entity_release(entity); } void os_mutex_take(OS_Handle mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(mutex.u64[0]); EnterCriticalSection(&entity->mutex); } void os_mutex_drop(OS_Handle mutex) { - OS_W32_Entity *entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); + OS_W32_Entity *entity = (OS_W32_Entity*)ptr_from_int(mutex.u64[0]); LeaveCriticalSection(&entity->mutex); } @@ -926,31 +926,31 @@ os_rw_mutex_alloc(void) { void os_rw_mutex_release(OS_Handle rw_mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(rw_mutex.u64[0]); os_w32_entity_release(entity); } void os_rw_mutex_take_r(OS_Handle rw_mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(rw_mutex.u64[0]); AcquireSRWLockShared(&entity->rw_mutex); } void os_rw_mutex_drop_r(OS_Handle rw_mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(rw_mutex.u64[0]); ReleaseSRWLockShared(&entity->rw_mutex); } void os_rw_mutex_take_w(OS_Handle rw_mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(rw_mutex.u64[0]); AcquireSRWLockExclusive(&entity->rw_mutex); } void os_rw_mutex_drop_w(OS_Handle rw_mutex) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(rw_mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(rw_mutex.u64[0]); ReleaseSRWLockExclusive(&entity->rw_mutex); } @@ -966,7 +966,7 @@ os_condition_variable_alloc(void) { void os_condition_variable_release(OS_Handle cv) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); os_w32_entity_release(entity); } @@ -975,8 +975,8 @@ os_condition_variable_wait(OS_Handle cv, OS_Handle mutex, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if (sleep_ms > 0) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity* mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); + OS_W32_Entity* mutex_entity = (OS_W32_Entity*)ptr_from_int(mutex.u64[0]); result = SleepConditionVariableCS(&entity->cv, &mutex_entity->mutex, sleep_ms); } return result; @@ -987,8 +987,8 @@ os_condition_variable_wait_rw_r(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { U32 sleep_ms = os_w32_sleep_ms_from_endt_us(endt_us); BOOL result = 0; if (sleep_ms > 0) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity* mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); + OS_W32_Entity* mutex_entity = (OS_W32_Entity*)ptr_from_int(mutex_rw.u64[0]); result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, CONDITION_VARIABLE_LOCKMODE_SHARED); } return result; @@ -1000,8 +1000,8 @@ os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { BOOL result = 0; if(sleep_ms > 0) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); - OS_W32_Entity* mutex_entity = (OS_W32_Entity*)PtrFromInt(mutex_rw.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); + OS_W32_Entity* mutex_entity = (OS_W32_Entity*)ptr_from_int(mutex_rw.u64[0]); result = SleepConditionVariableSRW(&entity->cv, &mutex_entity->rw_mutex, sleep_ms, 0); } return result; @@ -1009,13 +1009,13 @@ os_condition_variable_wait_rw_w(OS_Handle cv, OS_Handle mutex_rw, U64 endt_us) { void os_condition_variable_signal(OS_Handle cv) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); WakeConditionVariable(&entity->cv); } void os_condition_variable_broadcast(OS_Handle cv) { - OS_W32_Entity* entity = (OS_W32_Entity*)PtrFromInt(cv.u64[0]); + OS_W32_Entity* entity = (OS_W32_Entity*)ptr_from_int(cv.u64[0]); WakeAllConditionVariable(&entity->cv); } diff --git a/code/os/win32/os_win32.h b/code/os/win32/os_win32.h index 3c7d1b7..00f804a 100644 --- a/code/os/win32/os_win32.h +++ b/code/os/win32/os_win32.h @@ -81,7 +81,7 @@ struct OS_W32_State //////////////////////////////// //~ rjf: Globals -MD_API extern OS_W32_State os_w32_state = {0}; +MD_API extern OS_W32_State os_w32_state; //////////////////////////////// diff --git a/tests/code_sanity.c b/tests/code_sanity.c new file mode 100644 index 0000000..9c28426 --- /dev/null +++ b/tests/code_sanity.c @@ -0,0 +1,8 @@ +// This is test strictly for the granular (non-generated) version of the library to make sure it operates correctly + +#include "metadesk.c" + +int main() +{ + +}