From c00d139e556c7231aeb5ed61cd4c9999866f5a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sat, 4 Jan 2025 20:12:00 +0100 Subject: [PATCH 1/4] Further improve sleep accuracy on UNIX systems --- src/sdl/i_system.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 07088b957..4d62c4287 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2309,13 +2309,21 @@ void I_SleepDuration(precise_t duration) { #if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); - struct timespec ts = { - .tv_sec = duration / precision, - .tv_nsec = duration * 1000000000 / precision % 1000000000, - }; - int status; - do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); - while (status == EINTR); + precise_t dest = I_GetPreciseTime() + duration; + if (duration > 100000) + { + duration -= 100000; // 0.1 ms slack + struct timespec ts = { + .tv_sec = duration / precision, + .tv_nsec = duration * 1000000000 / precision % 1000000000, + }; + int status; + do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); + while (status == EINTR); + } + + // busy-wait the rest + while (((INT64)dest - (INT64)I_GetPreciseTime()) > 0); #elif defined (MIN_SLEEP_DURATION_MS) UINT64 precision = I_GetPrecisePrecision(); INT32 sleepvalue = cv_sleep.value; From d20552c49d9fd6a2075ebd7d46b0b133c69f1dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Sun, 5 Jan 2025 15:58:18 +0100 Subject: [PATCH 2/4] Adjust slack based on precision --- src/sdl/i_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 4d62c4287..18a5cb46d 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2310,9 +2310,9 @@ void I_SleepDuration(precise_t duration) #if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); precise_t dest = I_GetPreciseTime() + duration; - if (duration > 100000) + if (duration * 100000 / precision > 1) { - duration -= 100000; // 0.1 ms slack + duration -= (precision / 10000); // 0.1 ms slack struct timespec ts = { .tv_sec = duration / precision, .tv_nsec = duration * 1000000000 / precision % 1000000000, From 1da55066d43ed6a0cb666999c20316bef463024b Mon Sep 17 00:00:00 2001 From: Hanicef Date: Sun, 5 Jan 2025 19:18:57 +0100 Subject: [PATCH 3/4] Slight optimization --- src/sdl/i_system.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 18a5cb46d..f32d97e22 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2310,9 +2310,10 @@ void I_SleepDuration(precise_t duration) #if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); precise_t dest = I_GetPreciseTime() + duration; - if (duration * 100000 / precision > 1) + precise_t slack = (precision / 10000); // 0.1 ms slack + if (duration > slack) { - duration -= (precision / 10000); // 0.1 ms slack + duration -= slack; struct timespec ts = { .tv_sec = duration / precision, .tv_nsec = duration * 1000000000 / precision % 1000000000, From fb80091ac322c8a41bf8b983499596b5eec356b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= Date: Mon, 6 Jan 2025 09:49:04 +0100 Subject: [PATCH 4/4] Double slack time for busy-wait --- src/dedicated/i_system.c | 23 ++++++++++++++++------- src/sdl/i_system.c | 2 +- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/dedicated/i_system.c b/src/dedicated/i_system.c index 23c0149ca..79cdd9bb6 100644 --- a/src/dedicated/i_system.c +++ b/src/dedicated/i_system.c @@ -376,13 +376,22 @@ void I_SleepDuration(precise_t duration) { #if defined(__linux__) || defined(__FreeBSD__) UINT64 precision = I_GetPrecisePrecision(); - struct timespec ts = { - .tv_sec = duration / precision, - .tv_nsec = duration * 1000000000 / precision % 1000000000, - }; - int status; - do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); - while (status == EINTR); + precise_t dest = I_GetPreciseTime() + duration; + precise_t slack = (precision / 5000); // 0.2 ms slack + if (duration > slack) + { + duration -= slack; + struct timespec ts = { + .tv_sec = duration / precision, + .tv_nsec = duration * 1000000000 / precision % 1000000000, + }; + int status; + do status = clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts); + while (status == EINTR); + } + + // busy-wait the rest + while (((INT64)dest - (INT64)I_GetPreciseTime()) > 0); #else UINT64 precision = I_GetPrecisePrecision(); INT32 sleepvalue = cv_sleep.value; diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f32d97e22..f78f74d57 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -2310,7 +2310,7 @@ void I_SleepDuration(precise_t duration) #if defined(__linux__) || defined(__FreeBSD__) || defined(__HAIKU__) UINT64 precision = I_GetPrecisePrecision(); precise_t dest = I_GetPreciseTime() + duration; - precise_t slack = (precision / 10000); // 0.1 ms slack + precise_t slack = (precision / 5000); // 0.2 ms slack if (duration > slack) { duration -= slack;