Hosting on machines up for more than 24.8 days

GetTickCount and QueryPerformanceCounter counted from the host's boot; the
Xbox's count from power-on, and the game keeps times in signed 32-bit
variables. Past 2^31 ms of uptime (24.8 days), a hosted game timed out its
own client after about 15 s ("timeout in network_connection_idle", "the
game host went down"). Both clocks now count from when the game started,
beginning at 10 s.
This commit is contained in:
Milenko committed 2026-10-06 09:29:39 -04:00
1 parent 76addf661f
commit e9746abbee
1 file changed
+17 -7
+17 -7
View File
@@ -641,12 +641,26 @@ VOID WINAPI Sleep(DWORD milliseconds)
/* ---------- time */
DWORD WINAPI GetTickCount(void)
/* The game's clocks count from when it started, as the Xbox's count from
power-on. Its code keeps times in signed 32-bit variables, which a host up
for more than 24.8 days (2^31 ms since boot) overflows: a hosted game then
timed out its own clients. They start at 10 s, about where an Xbox's clock
is by the time the game runs. */
static unsigned long long platform_clock_nanoseconds(void)
{
static unsigned long long start;
struct timespec now;
unsigned long long value, expected = 0;
clock_gettime(CLOCK_MONOTONIC, &now);
return (DWORD)((unsigned long long)now.tv_sec * 1000ULL + (unsigned long long)now.tv_nsec / 1000000ULL);
value = (unsigned long long)now.tv_sec * 1000000000ULL + (unsigned long long)now.tv_nsec;
__atomic_compare_exchange_n(&start, &expected, value - 10000000000ULL, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
return value - __atomic_load_n(&start, __ATOMIC_RELAXED);
}
DWORD WINAPI GetTickCount(void)
{
return (DWORD)(platform_clock_nanoseconds() / 1000000ULL);
}
/* The Xbox performance counter runs at the 733 MHz CPU clock. Report a
@@ -656,11 +670,7 @@ arithmetic in the game stays in range, fine enough for frame timing. */
BOOL WINAPI QueryPerformanceCounter(LARGE_INTEGER *count)
{
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
count->QuadPart = (LONGLONG)((unsigned long long)now.tv_sec * PLATFORM_PERFORMANCE_FREQUENCY +
(unsigned long long)now.tv_nsec / (1000000000ULL / PLATFORM_PERFORMANCE_FREQUENCY));
count->QuadPart = (LONGLONG)(platform_clock_nanoseconds() / (1000000000ULL / PLATFORM_PERFORMANCE_FREQUENCY));
return TRUE;
}