swap testing
This commit is contained in:
parent
0f31e27d96
commit
05f6c937cb
@ -37,6 +37,10 @@
|
|||||||
# error Missing compile time definition for 'TestsAreEnabled'
|
# error Missing compile time definition for 'TestsAreEnabled'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HotSwappingIsEnabled
|
||||||
|
# error Missing compile time definition for 'HotSwappingIsEnabled'
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Machine context
|
//~ Machine context
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,16 @@
|
|||||||
typedef ExitFuncDef(ExitFunc);
|
typedef ExitFuncDef(ExitFunc);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ @hookdecl Exit operations
|
//~ @hookdecl Swap hooks
|
||||||
|
|
||||||
|
b32 IsSwappingIn(void);
|
||||||
|
b32 IsSwappingOut(void);
|
||||||
|
|
||||||
|
String SwappedStateFromName(Arena *arena, String name);
|
||||||
|
void WriteSwappedState(String name, String data);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ @hookdecl Exit hooks
|
||||||
|
|
||||||
void OnExit(ExitFunc *func);
|
void OnExit(ExitFunc *func);
|
||||||
void SignalExit(i32 code);
|
void SignalExit(i32 code);
|
||||||
|
|||||||
@ -109,6 +109,68 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Swap hooks
|
||||||
|
|
||||||
|
b32 IsSwappingIn(void)
|
||||||
|
{
|
||||||
|
return HotSwappingIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 IsSwappingOut(void)
|
||||||
|
{
|
||||||
|
return HotSwappingIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
String SwappedStateFromName(Arena *arena, String name)
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratch(arena);
|
||||||
|
String result = ZI;
|
||||||
|
String path = StringF(scratch.arena, "swap/%F.swp", FmtString(name));
|
||||||
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
|
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
u32 chunk_size = Kibi(64);
|
||||||
|
result.text = PushDry(arena, u8);
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
u8 *chunk = PushStructsNoZero(arena, u8, chunk_size);
|
||||||
|
u32 chunk_bytes_read = 0;
|
||||||
|
ReadFile(handle, chunk, chunk_size, (LPDWORD)&chunk_bytes_read, 0);
|
||||||
|
result.len += chunk_bytes_read;
|
||||||
|
if (chunk_bytes_read < chunk_size)
|
||||||
|
{
|
||||||
|
PopStructsNoCopy(arena, u8, chunk_size - chunk_bytes_read);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseHandle(handle);
|
||||||
|
EndScratch(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteSwappedState(String name, String data)
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
String result = ZI;
|
||||||
|
String path = StringF(scratch.arena, "swap/%F.swp", FmtString(name));
|
||||||
|
wchar_t *path_wstr = WstrFromString(scratch.arena, path);
|
||||||
|
HANDLE handle = CreateFileW(path_wstr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
if (handle != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
SetFilePointer(handle, 0, 0, FILE_BEGIN);
|
||||||
|
SetEndOfFile(handle);
|
||||||
|
WriteFile(handle, data.text, data.len, 0, 0);
|
||||||
|
}
|
||||||
|
CloseHandle(handle);
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ @hookdef Exit hooks
|
||||||
|
|
||||||
void OnExit(ExitFunc *func)
|
void OnExit(ExitFunc *func)
|
||||||
{
|
{
|
||||||
W32_SharedState *g = &W32_shared_state;
|
W32_SharedState *g = &W32_shared_state;
|
||||||
@ -254,10 +316,15 @@ i32 W32_Main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set up exit events */
|
/* Set up exit events */
|
||||||
g->panic_event = CreateEventW(0, 1, 0, 0);
|
#if HotSwappingIsEnabled
|
||||||
|
g->swap_event = CreateEventW(0, 1, 0, L"Local\\pp_swap_start");
|
||||||
|
#else
|
||||||
|
g->swap_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
#endif
|
||||||
|
g->panic_event = CreateEventW(0, 1, 0, 0);
|
||||||
g->startup_end_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_begin_event = CreateEventW(0, 1, 0, 0);
|
||||||
g->exit_end_event = CreateEventW(0, 1, 0, 0);
|
g->exit_end_event = CreateEventW(0, 1, 0, 0);
|
||||||
|
|
||||||
g->main_thread_id = GetCurrentThreadId();
|
g->main_thread_id = GetCurrentThreadId();
|
||||||
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
SetThreadDescription(GetCurrentThread(), L"Main thread");
|
||||||
@ -291,7 +358,7 @@ i32 W32_Main(void)
|
|||||||
{
|
{
|
||||||
HANDLE handles[] = {
|
HANDLE handles[] = {
|
||||||
g->startup_end_event,
|
g->startup_end_event,
|
||||||
g->panic_event
|
g->panic_event,
|
||||||
};
|
};
|
||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
}
|
}
|
||||||
@ -301,9 +368,10 @@ i32 W32_Main(void)
|
|||||||
{
|
{
|
||||||
HANDLE handles[] = {
|
HANDLE handles[] = {
|
||||||
g->exit_begin_event,
|
g->exit_begin_event,
|
||||||
g->panic_event
|
g->panic_event,
|
||||||
|
g->swap_event,
|
||||||
};
|
};
|
||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
DWORD wake = WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- App shutdown
|
//- App shutdown
|
||||||
@ -324,6 +392,16 @@ i32 W32_Main(void)
|
|||||||
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
WaitForMultipleObjects(countof(handles), handles, 0, INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Signal swap finish */
|
||||||
|
if (!Atomic32Fetch(&g->panicking) && IsSwappingOut())
|
||||||
|
{
|
||||||
|
HANDLE swap_end_event = OpenEventW(EVENT_MODIFY_STATE, 0, L"Local\\pp_swap_end");
|
||||||
|
if (swap_end_event != 0)
|
||||||
|
{
|
||||||
|
SetEvent(swap_end_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Exit */
|
/* Exit */
|
||||||
if (Atomic32Fetch(&g->panicking))
|
if (Atomic32Fetch(&g->panicking))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -38,6 +38,7 @@ Struct(W32_SharedState)
|
|||||||
Atomic32 panicking;
|
Atomic32 panicking;
|
||||||
wchar_t panic_wstr[4096];
|
wchar_t panic_wstr[4096];
|
||||||
HANDLE panic_event;
|
HANDLE panic_event;
|
||||||
|
HANDLE swap_event;
|
||||||
HANDLE startup_end_event;
|
HANDLE startup_end_event;
|
||||||
HANDLE exit_begin_event;
|
HANDLE exit_begin_event;
|
||||||
HANDLE exit_end_event;
|
HANDLE exit_end_event;
|
||||||
|
|||||||
@ -45,6 +45,10 @@
|
|||||||
# define TestsAreEnabled 0
|
# define TestsAreEnabled 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HotSwappingIsEnabled
|
||||||
|
# define HotSwappingIsEnabled 0
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Includes
|
//~ Includes
|
||||||
|
|
||||||
@ -96,6 +100,36 @@ LineCol LineColFromPos(String data, i64 pos)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Swap
|
||||||
|
|
||||||
|
#if PlatformIsWindows
|
||||||
|
u64 SignalSwapStart(void)
|
||||||
|
{
|
||||||
|
OS_Mkdir(Lit("swap"));
|
||||||
|
HANDLE swap_end_event = CreateEventW(0, 1, 0, L"Local\\pp_swap_end");
|
||||||
|
HANDLE swap_start_event = OpenEventW(EVENT_MODIFY_STATE, 0, L"Local\\pp_swap_start");
|
||||||
|
if (swap_start_event != 0)
|
||||||
|
{
|
||||||
|
SetEvent(swap_start_event);
|
||||||
|
CloseHandle(swap_start_event);
|
||||||
|
}
|
||||||
|
return (u64)swap_end_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForSwapEnd(u64 swap_start, i64 timeout_ns)
|
||||||
|
{
|
||||||
|
HANDLE swap_start_event = (HANDLE)swap_start;
|
||||||
|
if (swap_start_event != 0)
|
||||||
|
{
|
||||||
|
DWORD timeout_ms = timeout_ns / 1000000;
|
||||||
|
WaitForSingleObject(swap_start_event, timeout_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# error Swap signaling not implemented
|
||||||
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ OS command job
|
//~ OS command job
|
||||||
|
|
||||||
@ -138,7 +172,6 @@ Struct(CompilerParams)
|
|||||||
StringList linker_only_flags_clang;
|
StringList linker_only_flags_clang;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Build step job
|
//~ Build step job
|
||||||
|
|
||||||
@ -872,6 +905,8 @@ JobDef(Build, _, __)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 swap_start = SignalSwapStart();
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Args
|
//- Args
|
||||||
|
|
||||||
@ -895,6 +930,7 @@ JobDef(Build, _, __)
|
|||||||
PushStringToList(arena, &cp.defs, Lit("-DProfilingIsEnabled=0"));
|
PushStringToList(arena, &cp.defs, Lit("-DProfilingIsEnabled=0"));
|
||||||
PushStringToList(arena, &cp.defs, Lit("-DUnoptimizedIsEnabled=1"));
|
PushStringToList(arena, &cp.defs, Lit("-DUnoptimizedIsEnabled=1"));
|
||||||
PushStringToList(arena, &cp.defs, Lit("-DTestsAreEnabled=0"));
|
PushStringToList(arena, &cp.defs, Lit("-DTestsAreEnabled=0"));
|
||||||
|
PushStringToList(arena, &cp.defs, Lit("-DHotSwappingIsEnabled=1"));
|
||||||
|
|
||||||
//- Msvc
|
//- Msvc
|
||||||
{
|
{
|
||||||
@ -1049,6 +1085,8 @@ JobDef(Build, _, __)
|
|||||||
|
|
||||||
//- Link
|
//- Link
|
||||||
|
|
||||||
|
WaitForSwapEnd(swap_start, NsFromSeconds(0.5f / 1000.f));
|
||||||
|
|
||||||
String exe_file = Lit("pp.exe");
|
String exe_file = Lit("pp.exe");
|
||||||
i64 link_elapsed_ns = 0;
|
i64 link_elapsed_ns = 0;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|||||||
43
src/pp/pp.c
43
src/pp/pp.c
@ -30,8 +30,36 @@ void StartupUser(void)
|
|||||||
g->local_to_user_client_store = AcquireClientStore();
|
g->local_to_user_client_store = AcquireClientStore();
|
||||||
g->local_to_user_client = AcquireClient(g->local_to_user_client_store);
|
g->local_to_user_client = AcquireClient(g->local_to_user_client_store);
|
||||||
|
|
||||||
|
/* Init from swap */
|
||||||
g->world_to_ui_xf = XformIdentity;
|
g->world_to_ui_xf = XformIdentity;
|
||||||
g->world_to_render_xf = XformIdentity;
|
g->world_to_render_xf = XformIdentity;
|
||||||
|
if (IsSwappingIn());
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
String swap_str = SwappedStateFromName(scratch.arena, Lit("pp_user"));
|
||||||
|
if (swap_str.len == sizeof(SwappedUserState))
|
||||||
|
{
|
||||||
|
SwappedUserState *swap = (SwappedUserState *)swap_str.text;
|
||||||
|
SharedUserState *old = &swap->s;
|
||||||
|
g->debug_following = old->debug_following;
|
||||||
|
g->debug_camera = old->debug_camera;
|
||||||
|
g->debug_camera_panning = old->debug_camera_panning;
|
||||||
|
g->debug_camera_pan_start = old->debug_camera_pan_start;
|
||||||
|
g->debug_draw = old->debug_draw;
|
||||||
|
g->screen_size = old->screen_size;
|
||||||
|
g->screen_cursor = old->screen_cursor;
|
||||||
|
g->ui_to_screen_xf = old->ui_to_screen_xf;
|
||||||
|
g->ui_size = old->ui_size;
|
||||||
|
g->ui_cursor = old->ui_cursor;
|
||||||
|
g->render_to_ui_xf = old->render_to_ui_xf;
|
||||||
|
g->render_size = old->render_size;
|
||||||
|
g->world_to_render_xf = old->world_to_render_xf;
|
||||||
|
g->world_to_ui_xf = old->world_to_ui_xf;
|
||||||
|
g->world_cursor = old->world_cursor;
|
||||||
|
g->focus_send = old->focus_send;
|
||||||
|
}
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
g->console_logs_arena = AcquireArena(Gibi(64));
|
g->console_logs_arena = AcquireArena(Gibi(64));
|
||||||
//P_RegisterLogCallback(ConsoleLogCallback, P_LogLevel_Success);
|
//P_RegisterLogCallback(ConsoleLogCallback, P_LogLevel_Success);
|
||||||
@ -55,6 +83,19 @@ ExitFuncDef(ShutdownUser)
|
|||||||
SharedUserState *g = &shared_user_state;
|
SharedUserState *g = &shared_user_state;
|
||||||
Atomic32Set(&g->shutdown, 1);
|
Atomic32Set(&g->shutdown, 1);
|
||||||
YieldOnFence(&g->shutdown_jobs_fence, g->shutdown_jobs_count);
|
YieldOnFence(&g->shutdown_jobs_fence, g->shutdown_jobs_count);
|
||||||
|
|
||||||
|
/* Swap out */
|
||||||
|
if (IsSwappingOut())
|
||||||
|
{
|
||||||
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
|
||||||
|
SwappedUserState *swap = PushStruct(scratch.arena, SwappedUserState);
|
||||||
|
swap->s = *g;
|
||||||
|
WriteSwappedState(Lit("pp_user"), StringFromStruct(swap));
|
||||||
|
|
||||||
|
EndScratch(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
P_ReleaseWindow(g->window);
|
P_ReleaseWindow(g->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3215,9 +3256,11 @@ JobDef(UpdateSim, UNUSED sig, UNUSED id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
ReleaseClientStore(store);
|
ReleaseClientStore(store);
|
||||||
ReleaseSimAccel(&accel);
|
ReleaseSimAccel(&accel);
|
||||||
BB_ReleaseBuff(&snapshot_writer_bb);
|
BB_ReleaseBuff(&snapshot_writer_bb);
|
||||||
BB_ReleaseBuff(&msg_writer_bb);
|
BB_ReleaseBuff(&msg_writer_bb);
|
||||||
N_ReleaseHost(host);
|
N_ReleaseHost(host);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -264,6 +264,14 @@ Struct(SharedUserState)
|
|||||||
Vec2 focus_send;
|
Vec2 focus_send;
|
||||||
} extern shared_user_state;
|
} extern shared_user_state;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//~ Swap types
|
||||||
|
|
||||||
|
Struct(SwappedUserState)
|
||||||
|
{
|
||||||
|
SharedUserState s;
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
//~ Startup
|
//~ Startup
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user