Merge branch 'use-unix-nanosleep' into 'next'

Use nanosleep for I_SleepDuration on *nix

See merge request STJr/SRB2!2184
This commit is contained in:
Logan Aerl Arias 2023-12-25 23:59:17 +00:00
commit 3ba48ba43f
2 changed files with 52 additions and 41 deletions

View file

@ -30,12 +30,6 @@ static precise_t enterprecise, oldenterprecise;
static fixed_t entertic, oldentertics;
static double tictimer;
// A little more than the minimum sleep duration on Windows.
// May be incorrect for other platforms, but we don't currently have a way to
// query the scheduler granularity. SDL will do what's needed to make this as
// low as possible though.
#define MIN_SLEEP_DURATION_MS 2.1
tic_t I_GetTime(void)
{
return g_time.time;
@ -88,38 +82,3 @@ void I_UpdateTime(fixed_t timescale)
g_time.timefrac = FLOAT_TO_FIXED(fractional);
}
}
void I_SleepDuration(precise_t duration)
{
UINT64 precision = I_GetPrecisePrecision();
INT32 sleepvalue = cv_sleep.value;
UINT64 delaygranularity;
precise_t cur;
precise_t dest;
{
double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS));
delaygranularity = (UINT64)gran;
}
cur = I_GetPreciseTime();
dest = cur + duration;
// the reason this is not dest > cur is because the precise counter may wrap
// two's complement arithmetic is our friend here, though!
// e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
// 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
while ((INT64)(dest - cur) > 0)
{
// If our cv_sleep value exceeds the remaining sleep duration, use the
// hard sleep function.
if (sleepvalue > 0 && (dest - cur) > delaygranularity)
{
I_Sleep(sleepvalue);
}
// Otherwise, this is a spinloop.
cur = I_GetPreciseTime();
}
}

View file

@ -41,6 +41,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#include <ntsecapi.h>
#undef SystemFunction036
// A little more than the minimum sleep duration on Windows.
// May be incorrect for other platforms, but we don't currently have a way to
// query the scheduler granularity. SDL will do what's needed to make this as
// low as possible though.
#define MIN_SLEEP_DURATION_MS 2.1
#endif
#include <stdio.h>
#include <stdlib.h>
@ -2275,6 +2281,52 @@ void I_Sleep(UINT32 ms)
SDL_Delay(ms);
}
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);
#else
UINT64 precision = I_GetPrecisePrecision();
INT32 sleepvalue = cv_sleep.value;
UINT64 delaygranularity;
precise_t cur;
precise_t dest;
{
double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS));
delaygranularity = (UINT64)gran;
}
cur = I_GetPreciseTime();
dest = cur + duration;
// the reason this is not dest > cur is because the precise counter may wrap
// two's complement arithmetic is our friend here, though!
// e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
// 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
while ((INT64)(dest - cur) > 0)
{
// If our cv_sleep value exceeds the remaining sleep duration, use the
// hard sleep function.
if (sleepvalue > 0 && (dest - cur) > delaygranularity)
{
I_Sleep(sleepvalue);
}
// Otherwise, this is a spinloop.
cur = I_GetPreciseTime();
}
#endif
}
#ifdef NEWSIGNALHANDLER
ATTRNORETURN static FUNCNORETURN void newsignalhandler_Warn(const char *pr)
{