1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-27 09:32:40 +00:00

win32/pthread: implement clock_gettime for high-res timer purposes

Also apply some fixes to pthread_cond_timedwait while we're at it.

Note that by using GetSystemTimePreciseAsFileTime here we lose support
for Windows 7. This is considered acceptable.
This commit is contained in:
sfan5 2023-10-17 22:33:10 +02:00
parent 9f147496b5
commit 66c3110a85
2 changed files with 31 additions and 9 deletions

View File

@ -20,7 +20,7 @@
#include <sys/types.h>
#define _POSIX_TIMERS 0
#define _POSIX_TIMERS 200809L
// Note: all pthread functions are mangled to make static linking easier.
#define pthread_once m_pthread_once
@ -35,6 +35,7 @@
#define pthread_detach m_pthread_detach
#define pthread_create m_pthread_create
#define pthread_set_name_np m_pthread_set_name_np
#define clock_gettime m_clock_gettime
#define pthread_once_t INIT_ONCE
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
@ -76,6 +77,11 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex);
#define pthread_cond_broadcast(cond) WakeAllConditionVariable(cond)
#define pthread_cond_signal(cond) WakeConditionVariable(cond)
#define clockid_t int
#define CLOCK_REALTIME 1
int clock_gettime(clockid_t clockid, struct timespec *tp);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);

View File

@ -76,6 +76,23 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex)
return 0;
}
int clock_gettime(clockid_t clockid, struct timespec *tp)
{
if (clockid != CLOCK_REALTIME) {
errno = EINVAL;
return -1;
}
union {
FILETIME ft;
ULARGE_INTEGER i;
} r;
GetSystemTimePreciseAsFileTime(&r.ft);
r.i.QuadPart -= UINT64_C(116444736000000000); // MS epoch -> Unix epoch
tp->tv_sec = r.i.QuadPart / UINT64_C(10000000);
tp->tv_nsec = (r.i.QuadPart % UINT64_C(10000000)) * 100;
return 0;
}
static int cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
DWORD ms)
@ -95,16 +112,15 @@ int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime)
{
// mpv uses mingw's gettimeofday() as time source too.
struct timeval tv;
gettimeofday(&tv, NULL);
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
DWORD timeout_ms = 0;
if (abstime->tv_sec >= INT64_MAX / 10000) {
if (abstime->tv_sec >= INT64_MAX / 1000) { // overflow
timeout_ms = INFINITE;
} else if (abstime->tv_sec >= tv.tv_sec) {
long long msec = (abstime->tv_sec - tv.tv_sec) * 1000LL +
abstime->tv_nsec / 1000LL / 1000LL - tv.tv_usec / 1000LL;
if (msec > INT_MAX) {
} else if (abstime->tv_sec >= ts.tv_sec) {
int64_t msec = (abstime->tv_sec - ts.tv_sec) * INT64_C(1000) +
(abstime->tv_nsec - ts.tv_nsec) / INT64_C(10000000);
if (msec > ULONG_MAX) {
timeout_ms = INFINITE;
} else if (msec > 0) {
timeout_ms = msec;