summaryrefslogtreecommitdiffstats
path: root/osdep/win32
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2023-10-17 22:33:10 +0200
committersfan5 <sfan5@live.de>2023-10-20 21:30:51 +0200
commit66c3110a856f11c1fc68044e6ef426991911aa25 (patch)
tree32f83dbc5b0134e93f94649e8c3716fb716b2959 /osdep/win32
parent9f147496b50e1d281b61e9659401d0abdfc97d3f (diff)
downloadmpv-66c3110a856f11c1fc68044e6ef426991911aa25.tar.bz2
mpv-66c3110a856f11c1fc68044e6ef426991911aa25.tar.xz
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.
Diffstat (limited to 'osdep/win32')
-rw-r--r--osdep/win32/include/pthread.h8
-rw-r--r--osdep/win32/pthread.c32
2 files changed, 31 insertions, 9 deletions
diff --git a/osdep/win32/include/pthread.h b/osdep/win32/include/pthread.h
index e92c471f5f..76af00a514 100644
--- a/osdep/win32/include/pthread.h
+++ b/osdep/win32/include/pthread.h
@@ -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);
diff --git a/osdep/win32/pthread.c b/osdep/win32/pthread.c
index a178d72253..9bc7f0057d 100644
--- a/osdep/win32/pthread.c
+++ b/osdep/win32/pthread.c
@@ -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;