merge base_win32_entry & base_win32
This commit is contained in:
parent
ca9639affb
commit
2989e98d69
@ -18,7 +18,7 @@
|
|||||||
@Dep pp
|
@Dep pp
|
||||||
|
|
||||||
//- Api
|
//- Api
|
||||||
@IncludeC app_core.h
|
@IncludeC app.h
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
@IncludeC app_core.c
|
@IncludeC app.c
|
||||||
|
|||||||
@ -5,7 +5,7 @@ AC_SharedState AC_shared_state = ZI;
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Startup
|
//~ Startup
|
||||||
|
|
||||||
void AC_StartupCore(void)
|
void AC_Startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
AC_SharedState *g = &AC_shared_state;
|
AC_SharedState *g = &AC_shared_state;
|
||||||
|
|||||||
@ -65,7 +65,7 @@ extern AC_SharedState AC_shared_state;
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Startup
|
//~ Startup
|
||||||
|
|
||||||
void AC_StartupCore(void);
|
void AC_Startup(void);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Hash
|
//~ Hash
|
||||||
|
|||||||
@ -10,4 +10,4 @@
|
|||||||
@IncludeC asset_cache.c
|
@IncludeC asset_cache.c
|
||||||
|
|
||||||
//- Startup
|
//- Startup
|
||||||
@Startup AC_StartupCore
|
@Startup AC_Startup
|
||||||
|
|||||||
@ -640,22 +640,28 @@ Struct(StringList)
|
|||||||
# error FiberId not implemented
|
# error FiberId not implemented
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MaxFibers 1024
|
||||||
|
StaticAssert(MaxFibers < I16Max); /* Fiber id type should fit max threads */
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Exit callback types
|
||||||
|
|
||||||
|
#define ExitFuncDef(name) void name(void)
|
||||||
|
typedef ExitFuncDef(ExitFunc);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Core hooks
|
//~ @hookdecl Core hooks
|
||||||
|
|
||||||
void StartupBase(void);
|
|
||||||
StringList GetCommandLineArgs(void);
|
StringList GetCommandLineArgs(void);
|
||||||
b32 Panic(String msg);
|
b32 Panic(String msg);
|
||||||
b32 IsRunningInDebugger(void);
|
b32 IsRunningInDebugger(void);
|
||||||
void TrueRand(String buffer);
|
void TrueRand(String buffer);
|
||||||
|
void OnExit(ExitFunc *func);
|
||||||
#define MaxThreads 1024
|
void SignalExit(i32 code);
|
||||||
#define MaxFibers 1024
|
void ExitNow(i32 code);
|
||||||
StaticAssert(MaxThreads < I16Max); /* Thread id type should fit max threads */
|
|
||||||
StaticAssert(MaxFibers < I16Max); /* Fiber id type should fit max threads */
|
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdecl Layer startup hook (defined by metaprogram)
|
//~ @hookdecl Layer initialization hook (defined by metaprogram)
|
||||||
|
|
||||||
void StartupLayers(void);
|
void StartupLayers(void);
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Job queue types
|
//~ Job queue types
|
||||||
|
|
||||||
/* Work pools contain their own worker threads with their own thread priority
|
/* Work pools contain their own worker threads with their own thread priorities
|
||||||
* affinity based on the intended context of the pool. */
|
* and affinities based on the intended context of the pool. */
|
||||||
Enum(JobPool)
|
Enum(JobPool)
|
||||||
{
|
{
|
||||||
JobPool_Inherit = -1,
|
JobPool_Inherit = -1,
|
||||||
|
|||||||
@ -3,22 +3,12 @@ W32_SharedState W32_shared_state = ZI;
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ @hookdef Core hooks
|
//~ @hookdef Core hooks
|
||||||
|
|
||||||
//- Startup
|
|
||||||
void StartupBase(void)
|
|
||||||
{
|
|
||||||
W32_SharedState *g = &W32_shared_state;
|
|
||||||
g->tls_index = TlsAlloc();
|
|
||||||
TlsSetValue(g->tls_index, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Command line args
|
|
||||||
StringList GetCommandLineArgs(void)
|
StringList GetCommandLineArgs(void)
|
||||||
{
|
{
|
||||||
StringList result = ZI;
|
StringList result = ZI;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Panic
|
|
||||||
b32 Panic(String msg)
|
b32 Panic(String msg)
|
||||||
{
|
{
|
||||||
char msg_cstr[4096];
|
char msg_cstr[4096];
|
||||||
@ -40,14 +30,260 @@ b32 Panic(String msg)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Debugger check
|
|
||||||
b32 IsRunningInDebugger(void)
|
b32 IsRunningInDebugger(void)
|
||||||
{
|
{
|
||||||
return IsDebuggerPresent();
|
return IsDebuggerPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
//- True randomness
|
|
||||||
void TrueRand(String buffer)
|
void TrueRand(String buffer)
|
||||||
{
|
{
|
||||||
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnExit(ExitFunc *func)
|
||||||
|
{
|
||||||
|
W32_SharedState *g = &W32_shared_state;
|
||||||
|
i32 index = Atomic32FetchAdd(&g->num_exit_funcs, 1);
|
||||||
|
if (index >= W32_MaxOnExitFuncs)
|
||||||
|
{
|
||||||
|
Panic(Lit("Maximum on exit functions registered"));
|
||||||
|
}
|
||||||
|
g->exit_funcs[index] = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalExit(i32 code)
|
||||||
|
{
|
||||||
|
W32_SharedState *g = &W32_shared_state;
|
||||||
|
Atomic32FetchSet(&g->exit_code, code);
|
||||||
|
SetEvent(g->exit_begin_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExitNow(i32 code)
|
||||||
|
{
|
||||||
|
ExitProcess(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Startup / shutdown jobs
|
||||||
|
|
||||||
|
JobDef(W32_StartupLayersJob, UNUSED sig, UNUSED id)
|
||||||
|
{
|
||||||
|
W32_SharedState *g = &W32_shared_state;
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
{
|
||||||
|
StartupLayers();
|
||||||
|
SetEvent(g->startup_end_event);
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
JobDef(W32_ShutdownLayersJob, UNUSED sig, UNUSED id)
|
||||||
|
{
|
||||||
|
__prof;
|
||||||
|
W32_SharedState *g = &W32_shared_state;
|
||||||
|
i32 num_funcs = Atomic32Fetch(&g->num_exit_funcs);
|
||||||
|
for (i32 i = num_funcs - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
ExitFunc *func = g->exit_funcs[i];
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
SetEvent(g->exit_end_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Main
|
||||||
|
|
||||||
|
i32 W32_Main(void)
|
||||||
|
{
|
||||||
|
__profthread("Main thread", PROF_THREAD_GROUP_MAIN);
|
||||||
|
W32_SharedState *g = &W32_shared_state;
|
||||||
|
|
||||||
|
#if ProfilingIsEnabled
|
||||||
|
/* Start profiler */
|
||||||
|
{
|
||||||
|
__profn("Launch profiler");
|
||||||
|
STARTUPINFO si = ZI;
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
PROCESS_INFORMATION pi = ZI;
|
||||||
|
wchar_t cmd[sizeof(ProfilingCmdWstr)] = ZI;
|
||||||
|
CopyBytes(cmd, ProfilingCmdWstr, sizeof(ProfilingCmdWstr));
|
||||||
|
DeleteFileW(ProfilingOutFileWstr);
|
||||||
|
b32 success = CreateProcessW(0, cmd, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
MessageBoxExW(0, L"Failed to launch profiler using command '" ProfilingCmdWstr L"'.", L"Error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Set internal profiler thread affinities */
|
||||||
|
{
|
||||||
|
__profn("Set profiler thread affinities");
|
||||||
|
wchar_t *prefix_name_wstr = ProfilerThreadPrefixWstr;
|
||||||
|
u64 prefix_name_wstr_len = ((i32)sizeof(ProfilerThreadPrefixWstr) >> 1) - 1;
|
||||||
|
if (prefix_name_wstr_len > 0 && ProfilerThreadAffinityMask != 0)
|
||||||
|
{
|
||||||
|
DWORD proc_id = GetCurrentProcessId();
|
||||||
|
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
|
if (snapshot != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
THREADENTRY32 te = ZI;
|
||||||
|
te.dwSize = sizeof(THREADENTRY32);
|
||||||
|
if (Thread32First(snapshot, &te))
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (te.th32OwnerProcessID == proc_id)
|
||||||
|
{
|
||||||
|
i32 thread_id = te.th32ThreadID;
|
||||||
|
HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
|
||||||
|
if (thread)
|
||||||
|
{
|
||||||
|
wchar_t *thread_name_wstr = 0;
|
||||||
|
HRESULT hr = GetThreadDescription(thread, &thread_name_wstr);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
u64 thread_name_len = WstrLenNoLimit(thread_name_wstr);
|
||||||
|
if (thread_name_len >= prefix_name_wstr_len && EqBytes(thread_name_wstr, prefix_name_wstr, prefix_name_wstr_len))
|
||||||
|
{
|
||||||
|
__profn("Set profiler thread affinity");
|
||||||
|
b32 success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
|
||||||
|
{
|
||||||
|
/* Retry until external tools can set correct process affinity */
|
||||||
|
i32 delay_ms = 16;
|
||||||
|
while (!success && delay_ms <= 1024)
|
||||||
|
{
|
||||||
|
__profn("Profiler thread affinity retry");
|
||||||
|
Sleep(delay_ms);
|
||||||
|
success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
|
||||||
|
delay_ms *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert(success);
|
||||||
|
LAX success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (Thread32Next(snapshot, &te));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(snapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set up exit events */
|
||||||
|
g->panic_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
g->startup_end_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
g->exit_end_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
|
||||||
|
g->main_thread_id = GetCurrentThreadId();
|
||||||
|
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||||
|
|
||||||
|
/* Query system info */
|
||||||
|
GetSystemInfo(&g->info);
|
||||||
|
|
||||||
|
//- Startup jobs
|
||||||
|
StartupBaseJobs();
|
||||||
|
|
||||||
|
/* Startup layers */
|
||||||
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
RunJob(1, W32_StartupLayersJob, JobPool_Floating, JobPriority_High, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for startup end or panic */
|
||||||
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
HANDLE handles[] = {
|
||||||
|
g->startup_end_event,
|
||||||
|
g->panic_event
|
||||||
|
};
|
||||||
|
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for exit start or panic */
|
||||||
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
HANDLE handles[] = {
|
||||||
|
g->exit_begin_event,
|
||||||
|
g->panic_event
|
||||||
|
};
|
||||||
|
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- App shutdown
|
||||||
|
|
||||||
|
/* Run exit callbacks job */
|
||||||
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
RunJob(1, W32_ShutdownLayersJob, JobPool_Floating, JobPriority_High, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for exit end or panic */
|
||||||
|
if (!Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
HANDLE handles[] = {
|
||||||
|
g->exit_end_event,
|
||||||
|
g->panic_event
|
||||||
|
};
|
||||||
|
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit */
|
||||||
|
if (Atomic32Fetch(&g->panicking))
|
||||||
|
{
|
||||||
|
WaitForSingleObject(g->panic_event, INFINITE);
|
||||||
|
MessageBoxExW(0, g->panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
||||||
|
Atomic32FetchTestSet(&g->exit_code, 0, 1);
|
||||||
|
}
|
||||||
|
return Atomic32Fetch(&g->exit_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Crt main
|
||||||
|
|
||||||
|
#if CrtlibIsEnabled
|
||||||
|
# if IsConsoleApp
|
||||||
|
int main(char **argc, int argv)
|
||||||
|
{
|
||||||
|
LAX argc;
|
||||||
|
LAX argv;
|
||||||
|
return W32_Main();
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
|
||||||
|
{
|
||||||
|
LAX instance;
|
||||||
|
LAX prev_instance;
|
||||||
|
LAX cmdline_wstr;
|
||||||
|
LAX show_code;
|
||||||
|
return W32_Main();
|
||||||
|
}
|
||||||
|
# endif /* IsConsoleApp */
|
||||||
|
#endif /* CrtlibIsEnabled */
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Crt stub
|
||||||
|
|
||||||
|
#if !CrtlibIsEnabled
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
||||||
|
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
||||||
|
|
||||||
|
/* Enable floating point */
|
||||||
|
__attribute((used))
|
||||||
|
int _fltused;
|
||||||
|
|
||||||
|
__attribute((used))
|
||||||
|
void __stdcall wWinMainCRTStartup(void)
|
||||||
|
{
|
||||||
|
i32 result = W32_Main();
|
||||||
|
ExitProcess(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
#endif /* !CrtlibIsEnabled */
|
||||||
|
|||||||
@ -13,10 +13,37 @@ u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Shared state
|
//~ Shared state
|
||||||
|
|
||||||
|
#define W32_MaxOnExitFuncs 1024
|
||||||
|
|
||||||
Struct(W32_SharedState)
|
Struct(W32_SharedState)
|
||||||
{
|
{
|
||||||
DWORD tls_index;
|
SYSTEM_INFO info;
|
||||||
|
u32 main_thread_id;
|
||||||
|
Atomic32 shutdown;
|
||||||
Atomic32 exit_code;
|
Atomic32 exit_code;
|
||||||
|
|
||||||
|
//- Application control flow
|
||||||
|
Atomic32 panicking;
|
||||||
|
wchar_t panic_wstr[4096];
|
||||||
|
HANDLE panic_event;
|
||||||
|
HANDLE startup_end_event;
|
||||||
|
HANDLE exit_begin_event;
|
||||||
|
HANDLE exit_end_event;
|
||||||
|
|
||||||
|
//- Exit funcs
|
||||||
|
Atomic32 num_exit_funcs;
|
||||||
|
ExitFunc *exit_funcs[W32_MaxOnExitFuncs];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern W32_SharedState W32_shared_state;
|
extern W32_SharedState W32_shared_state;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Startup / shutdown jobs
|
||||||
|
|
||||||
|
JobDecl(W32_StartupLayersJob, EmptySig);
|
||||||
|
JobDecl(W32_ShutdownLayersJob, EmptySig);
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ Main
|
||||||
|
|
||||||
|
i32 W32_Main(void);
|
||||||
|
|||||||
@ -1,253 +0,0 @@
|
|||||||
W32_SharedEntryCtx W32_shared_entry_ctx = ZI;
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Startup / shutdown jobs
|
|
||||||
|
|
||||||
JobDef(W32_StartupLayersJob, UNUSED sig, UNUSED id)
|
|
||||||
{
|
|
||||||
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
|
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
|
||||||
{
|
|
||||||
StartupLayers();
|
|
||||||
SetEvent(g->startup_end_event);
|
|
||||||
}
|
|
||||||
EndScratch(scratch);
|
|
||||||
}
|
|
||||||
|
|
||||||
JobDef(W32_ShutdownLayersJob, UNUSED sig, UNUSED id)
|
|
||||||
{
|
|
||||||
__prof;
|
|
||||||
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
|
|
||||||
i32 num_funcs = Atomic32Fetch(&g->num_exit_funcs);
|
|
||||||
for (i32 i = num_funcs - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
ExitFunc *func = g->exit_funcs[i];
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
SetEvent(g->exit_end_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ @hookdef Exit hooks
|
|
||||||
|
|
||||||
void OnExit(ExitFunc *func)
|
|
||||||
{
|
|
||||||
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
|
|
||||||
i32 index = Atomic32FetchAdd(&g->num_exit_funcs, 1);
|
|
||||||
if (index >= W32_MaxOnExitFuncs)
|
|
||||||
{
|
|
||||||
Panic(Lit("Maximum on exit functions registered"));
|
|
||||||
}
|
|
||||||
g->exit_funcs[index] = func;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalExit(i32 code)
|
|
||||||
{
|
|
||||||
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
|
|
||||||
Atomic32FetchSet(&g->exit_code, code);
|
|
||||||
SetEvent(g->exit_begin_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExitNow(i32 code)
|
|
||||||
{
|
|
||||||
ExitProcess(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Main
|
|
||||||
|
|
||||||
i32 W32_Main(void)
|
|
||||||
{
|
|
||||||
__profthread("Main thread", PROF_THREAD_GROUP_MAIN);
|
|
||||||
W32_SharedEntryCtx *g = &W32_shared_entry_ctx;
|
|
||||||
|
|
||||||
#if ProfilingIsEnabled
|
|
||||||
/* Start profiler */
|
|
||||||
{
|
|
||||||
__profn("Launch profiler");
|
|
||||||
STARTUPINFO si = ZI;
|
|
||||||
si.cb = sizeof(si);
|
|
||||||
PROCESS_INFORMATION pi = ZI;
|
|
||||||
wchar_t cmd[sizeof(ProfilingCmdWstr)] = ZI;
|
|
||||||
CopyBytes(cmd, ProfilingCmdWstr, sizeof(ProfilingCmdWstr));
|
|
||||||
DeleteFileW(ProfilingOutFileWstr);
|
|
||||||
b32 success = CreateProcessW(0, cmd, 0, 0, 0, DETACHED_PROCESS, 0, 0, &si, &pi);
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
MessageBoxExW(0, L"Failed to launch profiler using command '" ProfilingCmdWstr L"'.", L"Error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Set internal profiler thread affinities */
|
|
||||||
{
|
|
||||||
__profn("Set profiler thread affinities");
|
|
||||||
wchar_t *prefix_name_wstr = ProfilerThreadPrefixWstr;
|
|
||||||
u64 prefix_name_wstr_len = ((i32)sizeof(ProfilerThreadPrefixWstr) >> 1) - 1;
|
|
||||||
if (prefix_name_wstr_len > 0 && ProfilerThreadAffinityMask != 0)
|
|
||||||
{
|
|
||||||
DWORD proc_id = GetCurrentProcessId();
|
|
||||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
|
||||||
if (snapshot != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
THREADENTRY32 te = ZI;
|
|
||||||
te.dwSize = sizeof(THREADENTRY32);
|
|
||||||
if (Thread32First(snapshot, &te))
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (te.th32OwnerProcessID == proc_id)
|
|
||||||
{
|
|
||||||
i32 thread_id = te.th32ThreadID;
|
|
||||||
HANDLE thread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id);
|
|
||||||
if (thread)
|
|
||||||
{
|
|
||||||
wchar_t *thread_name_wstr = 0;
|
|
||||||
HRESULT hr = GetThreadDescription(thread, &thread_name_wstr);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
u64 thread_name_len = WstrLenNoLimit(thread_name_wstr);
|
|
||||||
if (thread_name_len >= prefix_name_wstr_len && EqBytes(thread_name_wstr, prefix_name_wstr, prefix_name_wstr_len))
|
|
||||||
{
|
|
||||||
__profn("Set profiler thread affinity");
|
|
||||||
b32 success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
|
|
||||||
{
|
|
||||||
/* Retry until external tools can set correct process affinity */
|
|
||||||
i32 delay_ms = 16;
|
|
||||||
while (!success && delay_ms <= 1024)
|
|
||||||
{
|
|
||||||
__profn("Profiler thread affinity retry");
|
|
||||||
Sleep(delay_ms);
|
|
||||||
success = SetThreadAffinityMask(thread, ProfilerThreadAffinityMask) != 0;
|
|
||||||
delay_ms *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Assert(success);
|
|
||||||
LAX success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (Thread32Next(snapshot, &te));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(snapshot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Set up exit events */
|
|
||||||
g->panic_event = CreateEventW(0, 1, 0, 0);
|
|
||||||
g->startup_end_event = CreateEventW(0, 1, 0, 0);
|
|
||||||
g->exit_begin_event = CreateEventW(0, 1, 0, 0);
|
|
||||||
g->exit_end_event = CreateEventW(0, 1, 0, 0);
|
|
||||||
|
|
||||||
g->main_thread_id = GetCurrentThreadId();
|
|
||||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
|
||||||
|
|
||||||
/* Query system info */
|
|
||||||
GetSystemInfo(&g->info);
|
|
||||||
|
|
||||||
//- Startup jobs
|
|
||||||
StartupBaseJobs();
|
|
||||||
|
|
||||||
/* Startup layers */
|
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
RunJob(1, W32_StartupLayersJob, JobPool_Floating, JobPriority_High, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for startup end or panic */
|
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
HANDLE handles[] = {
|
|
||||||
g->startup_end_event,
|
|
||||||
g->panic_event
|
|
||||||
};
|
|
||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for exit start or panic */
|
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
HANDLE handles[] = {
|
|
||||||
g->exit_begin_event,
|
|
||||||
g->panic_event
|
|
||||||
};
|
|
||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//- App shutdown
|
|
||||||
|
|
||||||
/* Run exit callbacks job */
|
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
RunJob(1, W32_ShutdownLayersJob, JobPool_Floating, JobPriority_High, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for exit end or panic */
|
|
||||||
if (!Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
HANDLE handles[] = {
|
|
||||||
g->exit_end_event,
|
|
||||||
g->panic_event
|
|
||||||
};
|
|
||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit */
|
|
||||||
if (Atomic32Fetch(&g->panicking))
|
|
||||||
{
|
|
||||||
WaitForSingleObject(g->panic_event, INFINITE);
|
|
||||||
MessageBoxExW(0, g->panic_wstr, L"Fatal error", MB_ICONSTOP | MB_SETFOREGROUND | MB_TOPMOST, 0);
|
|
||||||
Atomic32FetchTestSet(&g->exit_code, 0, 1);
|
|
||||||
}
|
|
||||||
return Atomic32Fetch(&g->exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Crt main
|
|
||||||
|
|
||||||
#if CrtlibIsEnabled
|
|
||||||
# if IsConsoleApp
|
|
||||||
int main(char **argc, int argv)
|
|
||||||
{
|
|
||||||
LAX argc;
|
|
||||||
LAX argv;
|
|
||||||
return W32_Main();
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance, _In_ LPWSTR cmdline_wstr, _In_ int show_code)
|
|
||||||
{
|
|
||||||
LAX instance;
|
|
||||||
LAX prev_instance;
|
|
||||||
LAX cmdline_wstr;
|
|
||||||
LAX show_code;
|
|
||||||
return W32_Main();
|
|
||||||
}
|
|
||||||
# endif /* IsConsoleApp */
|
|
||||||
#endif /* CrtlibIsEnabled */
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Crt stub
|
|
||||||
|
|
||||||
#if !CrtlibIsEnabled
|
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
|
||||||
#pragma clang diagnostic ignored "-Wmissing-prototypes"
|
|
||||||
|
|
||||||
/* Enable floating point */
|
|
||||||
__attribute((used))
|
|
||||||
int _fltused;
|
|
||||||
|
|
||||||
__attribute((used))
|
|
||||||
void __stdcall wWinMainCRTStartup(void)
|
|
||||||
{
|
|
||||||
i32 result = W32_Main();
|
|
||||||
ExitProcess(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
|
|
||||||
#endif /* !CrtlibIsEnabled */
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
////////////////////////////////
|
|
||||||
//~ Shared state
|
|
||||||
|
|
||||||
#define W32_MaxOnExitFuncs 1024
|
|
||||||
|
|
||||||
Struct(W32_SharedEntryCtx)
|
|
||||||
{
|
|
||||||
SYSTEM_INFO info;
|
|
||||||
u32 main_thread_id;
|
|
||||||
Atomic32 shutdown;
|
|
||||||
Atomic32 exit_code;
|
|
||||||
|
|
||||||
//- Application control flow
|
|
||||||
Atomic32 panicking;
|
|
||||||
wchar_t panic_wstr[4096];
|
|
||||||
HANDLE panic_event;
|
|
||||||
HANDLE startup_end_event;
|
|
||||||
HANDLE exit_begin_event;
|
|
||||||
HANDLE exit_end_event;
|
|
||||||
|
|
||||||
//- Exit funcs
|
|
||||||
Atomic32 num_exit_funcs;
|
|
||||||
ExitFunc *exit_funcs[W32_MaxOnExitFuncs];
|
|
||||||
};
|
|
||||||
|
|
||||||
extern W32_SharedEntryCtx W32_shared_entry_ctx;
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Startup / shutdown jobs
|
|
||||||
|
|
||||||
JobDecl(W32_StartupLayersJob, EmptySig);
|
|
||||||
JobDecl(W32_ShutdownLayersJob, EmptySig);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ Main
|
|
||||||
|
|
||||||
i32 W32_Main(void);
|
|
||||||
@ -1,9 +1,7 @@
|
|||||||
//- Api
|
//- Api
|
||||||
#include "base_win32.h"
|
#include "base_win32.h"
|
||||||
#include "base_win32_entry.h"
|
|
||||||
#include "base_win32_job.h"
|
#include "base_win32_job.h"
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
#include "base_win32.c"
|
#include "base_win32.c"
|
||||||
#include "base_win32_entry.c"
|
|
||||||
#include "base_win32_job.c"
|
#include "base_win32_job.c"
|
||||||
|
|||||||
@ -125,6 +125,7 @@ void StartupBaseJobs(void)
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Shutdown
|
//~ Shutdown
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void ShutdownJobs(void)
|
void ShutdownJobs(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,10 +8,10 @@
|
|||||||
@Dep collider
|
@Dep collider
|
||||||
|
|
||||||
//- Api
|
//- Api
|
||||||
@IncludeC draw_core.h
|
@IncludeC draw.h
|
||||||
|
|
||||||
//- Impl
|
//- Impl
|
||||||
@IncludeC draw_core.c
|
@IncludeC draw.c
|
||||||
|
|
||||||
//- Init
|
//- Init
|
||||||
@Startup D_StartupCore
|
@Startup D_StartupCore
|
||||||
|
|||||||
@ -854,10 +854,6 @@ void StartupMeta(void)
|
|||||||
PushStringToList(arena, &c_out_lines, Lit("//- Startup"));
|
PushStringToList(arena, &c_out_lines, Lit("//- Startup"));
|
||||||
PushStringToList(arena, &c_out_lines, Lit("void StartupLayers(void)"));
|
PushStringToList(arena, &c_out_lines, Lit("void StartupLayers(void)"));
|
||||||
PushStringToList(arena, &c_out_lines, Lit("{"));
|
PushStringToList(arena, &c_out_lines, Lit("{"));
|
||||||
{
|
|
||||||
String line = Lit(" StartupBase();");
|
|
||||||
PushStringToList(arena, &c_out_lines, line);
|
|
||||||
}
|
|
||||||
for (L_TopoItem *item = topo.startup_functions.first; item; item = item->next)
|
for (L_TopoItem *item = topo.startup_functions.first; item; item = item->next)
|
||||||
{
|
{
|
||||||
String line = StringF(arena, " %F();", FmtString(item->s));
|
String line = StringF(arena, " %F();", FmtString(item->s));
|
||||||
@ -987,7 +983,6 @@ void StartupMeta(void)
|
|||||||
|
|
||||||
void StartupLayers(void)
|
void StartupLayers(void)
|
||||||
{
|
{
|
||||||
StartupBase();
|
|
||||||
OS_Startup();
|
OS_Startup();
|
||||||
StartupMeta();
|
StartupMeta();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,9 +3,6 @@
|
|||||||
|
|
||||||
void OS_Startup(void)
|
void OS_Startup(void)
|
||||||
{
|
{
|
||||||
W32_SharedState *g = &W32_shared_state;
|
|
||||||
g->tls_index = TlsAlloc();
|
|
||||||
TlsSetValue(g->tls_index, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user