From e9746abbee643cf42e9e87ccb1ac65ac6ccd2a80 Mon Sep 17 00:00:00 2001 From: Milenko <39630670+MrMilenko@users.noreply.github.com> Date: Tue, 29 Sep 2026 22:24:14 -0400 Subject: [PATCH] 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. --- port/linux/src/xbox_kernel.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/port/linux/src/xbox_kernel.c b/port/linux/src/xbox_kernel.c index 04fc3267..7c188532 100644 --- a/port/linux/src/xbox_kernel.c +++ b/port/linux/src/xbox_kernel.c @@ -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; }