From d867a8b0c0ce725e1f547b25c366f721bf746a86 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 9 Feb 2025 02:20:36 -0500 Subject: [PATCH] setup os_init() for manually starting up os_context --- .vscode/settings.json | 3 +- code/base/thread_context.c | 2 +- code/mdesk/mdesk.c | 10 ++- code/mdesk/mdesk.h | 19 ++++-- code/os/linux/os_linux.c | 2 +- code/os/os.h | 14 ++++ code/os/win32/os_win32.c | 135 ++++++++++++++++++++++++++++++++++++- code/os/win32/os_win32.h | 1 - tests/code_sanity.c | 2 +- 9 files changed, 170 insertions(+), 18 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 925f880..6054e97 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -83,7 +83,8 @@ "metadesk.h": "c", "mdesk.h": "c", "text.h": "c", - "forward_list": "c" + "forward_list": "c", + "iomanip": "cpp" }, "workbench.colorCustomizations": { "activityBar.activeBackground": "#713fb8", diff --git a/code/base/thread_context.c b/code/base/thread_context.c index 04fb2bd..749c0a6 100644 --- a/code/base/thread_context.c +++ b/code/base/thread_context.c @@ -18,7 +18,7 @@ MD_API_C thread_static TCTX* tctx_thread_local = 0; void tctx_init_and_equip(TCTX* tctx) { - memory_zero_struct(tctx); + // memory_zero_struct(tctx); Arena** arena_ptr = tctx->arenas; for (U64 i = 0; i < array_count(tctx->arenas); i += 1, arena_ptr += 1) diff --git a/code/mdesk/mdesk.c b/code/mdesk/mdesk.c index fb183a2..7a448f2 100644 --- a/code/mdesk/mdesk.c +++ b/code/mdesk/mdesk.c @@ -10,17 +10,15 @@ 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); + if ( ! ctx->dont_init_os) { + os_init(& ctx->os_ctx, & ctx->thread_ctx); } + + } void deinit(Context* ctx) { - tctx_release(); } //////////////////////////////// diff --git a/code/mdesk/mdesk.h b/code/mdesk/mdesk.h index 953fa0c..b79bfcd 100644 --- a/code/mdesk/mdesk.h +++ b/code/mdesk/mdesk.h @@ -230,14 +230,18 @@ struct Context // Currently, this is only relevant if the user is utilizing this library via bindings // or they are not utilizing metadesk's hosted `entry_point` runtime - // 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 + // which will be utilized for thread local scratch arena TCTX thread_ctx; + + // Just as with TCTX its recommended the user setup the arena allocators + // for te os context + OS_Context os_ctx; + + // This skips the os_init process but that means the user is expected to setup + // the thread context for the process + B32 dont_init_os; }; //////////////////////////////// @@ -263,8 +267,11 @@ nil_node() //////////////////////////////// // Context lifetime Functios +// NOTE(Ed): The are see comments in Context struct, this is only necessary when not utilizing +// the metadesk os runtime provided entry_point interface + MD_API void init (Context* ctx); -MD_API void deinit(Context* ctx); +// MD_API void deinit(Context* ctx); //////////////////////////////// //~ rjf: Message Type Functions diff --git a/code/os/linux/os_linux.c b/code/os/linux/os_linux.c index b4efa12..d7af33e 100644 --- a/code/os/linux/os_linux.c +++ b/code/os/linux/os_linux.c @@ -100,7 +100,7 @@ void os_abort(S32 exit_code) { exit(exit_code); } OS_Handle os_file_open(OS_AccessFlags flags, String8 path) { - TempArena scratch = scratch_begin(0, 0); + TempArena scratch = scratch_begin(0, 0); { String8 path_copy = push_str8_copy(scratch.arena, path); int lnx_flags = 0; diff --git a/code/os/os.h b/code/os/os.h index b4d6867..bbbb287 100644 --- a/code/os/os.h +++ b/code/os/os.h @@ -482,3 +482,17 @@ MD_API OS_Guid os_make_guid(void); #if BUILD_ENTRY_DEFINING_UNIT void entry_point(CmdLine* cmdline); #endif + +//////////////////////////////// +//~ Ed: Manual OS Bootstrap (Implemented Per-OS) + +typedef struct OS_Context OS_Context; +struct OS_Context +{ + Arena* state_arena; + Arena* entity_arena; + B32 enable_large_pages; +}; + +// OS layer initialization +MD_API void os_init(OS_Context* ctx, TCTX* thread_ctx); diff --git a/code/os/win32/os_win32.c b/code/os/win32/os_win32.c index 149a757..3291ee9 100644 --- a/code/os/win32/os_win32.c +++ b/code/os/win32/os_win32.c @@ -1,6 +1,5 @@ #ifdef INTELLISENSE_DIRECTIVES # include "os_win32.h" -# include "os/os.h" #endif // Copyright (c) 2024 Epic Games Tools @@ -1522,3 +1521,137 @@ int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int // BUILD_ENTRY_POINT #endif + +//////////////////////////////// +//~ Ed: Manual OS Bootstrap + +void os_init(OS_Context* ctx, TCTX* thread_ctx) +{ + // rjf: dynamically load windows functions which are not guaranteed + // in all SDKs + { + HMODULE module = LoadLibraryA("kernel32.dll"); + w32_SetThreadDescription_func = (W32_SetThreadDescription_Type *)GetProcAddress(module, "SetThreadDescription"); + FreeLibrary(module); + } + + // rjf: try to enable large pages if we can + if (ctx->enable_large_pages) + { + HANDLE token; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + { + LUID luid; + if (LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) + { + TOKEN_PRIVILEGES priv; + priv.PrivilegeCount = 1; + priv.Privileges[0].Luid = luid; + priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(token, 0, &priv, sizeof(priv), 0, 0); + } + CloseHandle(token); + } + } + + SYSTEM_INFO sysinfo = {0}; + GetSystemInfo(&sysinfo); + + // rjf: set up non-dynamically-alloc'd state + // + // (we need to set up some basics before this layer can supply + // memory allocation primitives) + { + os_w32_state.microsecond_resolution = 1; + LARGE_INTEGER large_int_resolution; + if (QueryPerformanceFrequency(&large_int_resolution)) + { + os_w32_state.microsecond_resolution = large_int_resolution.QuadPart; + } + } + { + OS_SystemInfo* info = &os_w32_state.system_info; + info->logical_processor_count = (U64)sysinfo.dwNumberOfProcessors; + info->page_size = sysinfo.dwPageSize; + info->large_page_size = GetLargePageMinimum(); + info->allocation_granularity = sysinfo.dwAllocationGranularity; + } + { + OS_ProcessInfo* info = &os_w32_state.process_info; + info->pid = GetCurrentProcessId(); + } + + // rjf: set up thread context + tctx_init_and_equip(thread_ctx); + + // rjf: set up dynamically-alloc'd state + Arena* state_arena = ctx->entity_arena; + if (state_arena == nullptr) { + state_arena = arena_alloc(.backing = varena_allocator(varena_alloc(0))); + ctx->state_arena = state_arena; + } + { + os_w32_state.arena = state_arena; + { + OS_SystemInfo* info = &os_w32_state.system_info; + U8 buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0}; + DWORD size = MAX_COMPUTERNAME_LENGTH + 1; + if(GetComputerNameA((char*)buffer, &size)) + { + info->machine_name = push_str8_copy(state_arena, str8(buffer, size)); + } + } + } + { + OS_ProcessInfo* info = &os_w32_state.process_info; + { + TempArena scratch = scratch_begin(0, 0); + DWORD size = KB(32); + U16* buffer = push_array_no_zero(scratch.arena, U16, size); + DWORD length = GetModuleFileNameW(0, (WCHAR*)buffer, size); + String8 name8 = str8_from_16(scratch.arena, str16(buffer, length)); + String8 name_chopped = str8_chop_last_slash(name8); + info->binary_path = push_str8_copy(state_arena, name_chopped); + scratch_end(scratch); + } + + info->initial_path = os_get_current_path(state_arena); + { + TempArena scratch = scratch_begin(0, 0); + U64 size = KB(32); + U16* buffer = push_array_no_zero(scratch.arena, U16, size); + if (SUCCEEDED(SHGetFolderPathW(0, CSIDL_APPDATA, 0, 0, (WCHAR*)buffer))) { + info->user_program_data_path = str8_from_16(state_arena, str16_cstring(buffer)); + } + scratch_end(scratch); + } + { + WCHAR* this_proc_env = GetEnvironmentStringsW(); + U64 start_idx = 0; + for (U64 idx = 0;; idx += 1) + { + if (this_proc_env[idx] == 0) + { + if (start_idx == idx) + { + break; + } + else + { + String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx); + String8 string = str8_from_16(state_arena, string16); + str8_list_push(state_arena, &info->environment, string); + start_idx = idx+1; + } + } + } + } + } + + // rjf: set up entity storage + InitializeCriticalSection(&os_w32_state.entity_mutex); + if (ctx->entity_arena == nullptr) { + ctx->entity_arena = arena_alloc(.backing = varena_allocator(varena_alloc(0))); + os_w32_state.entity_arena = ctx->entity_arena; + } +} diff --git a/code/os/win32/os_win32.h b/code/os/win32/os_win32.h index 00f804a..8c763a5 100644 --- a/code/os/win32/os_win32.h +++ b/code/os/win32/os_win32.h @@ -166,7 +166,6 @@ MD_API DWORD os_w32_thread_entry_point(void* ptr); inline String8 os_get_current_path_alloc(AllocatorInfo ainfo) { String8 name; - // TODO(Ed): Review TempArena scratch = scratch_begin(0, 0); { DWORD length = GetCurrentDirectoryW(0, 0); diff --git a/tests/code_sanity.c b/tests/code_sanity.c index 3d3180a..2e74216 100644 --- a/tests/code_sanity.c +++ b/tests/code_sanity.c @@ -4,7 +4,7 @@ int main() { - Context ctx; + Context ctx = {0}; init(& ctx);