Skip to content

Commit

Permalink
engine: platform: win32: implement nanosleep using waitable timers wi…
Browse files Browse the repository at this point in the history
…th high precision
  • Loading branch information
a1batross committed Feb 15, 2025
1 parent 052ea6a commit af6b434
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 27 deletions.
27 changes: 6 additions & 21 deletions engine/platform/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ void Android_Shutdown( void );
#endif

#if XASH_WIN32
void Win32_Init( void );
void Win32_Init( qboolean con_showalways );
void Win32_Shutdown( void );
qboolean Win32_NanoSleep( int nsec );
void Wcon_CreateConsole( qboolean con_showalways );
void Wcon_DestroyConsole( void );
void Wcon_InitConsoleCommands( void );
Expand Down Expand Up @@ -126,8 +127,7 @@ static inline void Platform_Init( qboolean con_showalways, const char *basedir )
#elif XASH_DOS
DOS_Init( );
#elif XASH_WIN32
Win32_Init( );
Wcon_CreateConsole( con_showalways );
Win32_Init( con_showalways );
#elif XASH_LINUX
Linux_Init( );
#endif
Expand All @@ -142,7 +142,6 @@ static inline void Platform_Shutdown( void )
#elif XASH_DOS
DOS_Shutdown( );
#elif XASH_WIN32
Wcon_DestroyConsole( );
Win32_Shutdown( );
#elif XASH_LINUX
Linux_Shutdown( );
Expand Down Expand Up @@ -193,23 +192,9 @@ static inline qboolean Platform_NanoSleep( int nsec )
};
return nanosleep( &ts, NULL ) == 0;
#elif XASH_WIN32
extern HANDLE g_waitable_timer;
const LARGE_INTEGER ts = { -nsec };

if( !g_waitable_timer )
return false;

if( !SetWaitableTimer( g_waitable_timer, &ts, 0, NULL, NULL, FALSE ))
{
CloseHandle( g_waitable_timer );
g_waitable_timer = 0;
return false;
}

if( WaitForSingleObject( g_waitable_timer, 1000 ) != WAIT_OBJECT_0 )
return false;

return true;
return Win32_NanoSleep( nsec );
#else
return false;
#endif
}

Expand Down
44 changes: 38 additions & 6 deletions engine/platform/win32/sys_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,63 @@ double Platform_DoubleTime( void )
}
#endif // XASH_TIMER == TIMER_WIN32

void Win32_Init( void )
void Win32_Init( qboolean con_showalways )
{
HMODULE hModule = LoadLibrary( "kernel32.dll" );

if( hModule )
{
HANDLE ( __stdcall *pfnCreateWaitableTimerExW)( LPSECURITY_ATTRIBUTES lpTimerAttributes, LPCWSTR lpTimerName, DWORD dwFlags, DWORD dwDesiredAccess );

if(( pfnCreateWaitableTimerExW = GetProcAddress( hModule, "CreateWaitableTimerExW" )))
if(( pfnCreateWaitableTimerExW = (void *)GetProcAddress( hModule, "CreateWaitableTimerExW" )))
{
// CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
g_waitable_timer = pfnCreateWaitableTimerExW( NULL, NULL, 0x1 | 0x2, 0 );
g_waitable_timer = pfnCreateWaitableTimerExW(
NULL,
NULL,
0x1 /* CREATE_WAITABLE_TIMER_MANUAL_RESET */ | 0x2 /* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION */,
0x0002 /* TIMER_MODIFY_STATE */ | SYNCHRONIZE | DELETE
);
}

FreeLibrary( "kernel32.dll" );
FreeLibrary( hModule );
}

#if 0 // FIXME: creates object but doesn't wait for specific time for me on Windows 10, with the code above commented
if( !g_waitable_timer )
g_waitable_timer = CreateWaitableTimer( NULL, TRUE, NULL );
#endif

Wcon_CreateConsole( con_showalways );
}

void Win32_Shutdown( void )
{
Wcon_DestroyConsole( );

if( g_waitable_timer )
{
CloseHandle( g_waitable_timer );
g_waitable_timer = 0;
}
}

qboolean Win32_NanoSleep( int nsec )
{
const LARGE_INTEGER ts = { -nsec };

if( !g_waitable_timer )
return false;

if( !SetWaitableTimer( g_waitable_timer, &ts, 0, NULL, NULL, FALSE ))
{
CloseHandle( g_waitable_timer );
g_waitable_timer = 0;
return false;
}

if( WaitForSingleObject( g_waitable_timer, Q_max( 1, nsec / 1000000 )) != WAIT_OBJECT_0 )
return false;

return true;
}

qboolean Platform_DebuggerPresent( void )
Expand Down

0 comments on commit af6b434

Please # to comment.