Skip to content

Commit 66c3110

Browse files
committed
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.
1 parent 9f14749 commit 66c3110

File tree

2 files changed

+31
-9
lines changed

2 files changed

+31
-9
lines changed

osdep/win32/include/pthread.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
#include <sys/types.h>
2222

23-
#define _POSIX_TIMERS 0
23+
#define _POSIX_TIMERS 200809L
2424

2525
// Note: all pthread functions are mangled to make static linking easier.
2626
#define pthread_once m_pthread_once
@@ -35,6 +35,7 @@
3535
#define pthread_detach m_pthread_detach
3636
#define pthread_create m_pthread_create
3737
#define pthread_set_name_np m_pthread_set_name_np
38+
#define clock_gettime m_clock_gettime
3839

3940
#define pthread_once_t INIT_ONCE
4041
#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
@@ -76,6 +77,11 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex);
7677
#define pthread_cond_broadcast(cond) WakeAllConditionVariable(cond)
7778
#define pthread_cond_signal(cond) WakeConditionVariable(cond)
7879

80+
#define clockid_t int
81+
#define CLOCK_REALTIME 1
82+
83+
int clock_gettime(clockid_t clockid, struct timespec *tp);
84+
7985
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
8086
pthread_mutex_t *restrict mutex,
8187
const struct timespec *restrict abstime);

osdep/win32/pthread.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex)
7676
return 0;
7777
}
7878

79+
int clock_gettime(clockid_t clockid, struct timespec *tp)
80+
{
81+
if (clockid != CLOCK_REALTIME) {
82+
errno = EINVAL;
83+
return -1;
84+
}
85+
union {
86+
FILETIME ft;
87+
ULARGE_INTEGER i;
88+
} r;
89+
GetSystemTimePreciseAsFileTime(&r.ft);
90+
r.i.QuadPart -= UINT64_C(116444736000000000); // MS epoch -> Unix epoch
91+
tp->tv_sec = r.i.QuadPart / UINT64_C(10000000);
92+
tp->tv_nsec = (r.i.QuadPart % UINT64_C(10000000)) * 100;
93+
return 0;
94+
}
95+
7996
static int cond_wait(pthread_cond_t *restrict cond,
8097
pthread_mutex_t *restrict mutex,
8198
DWORD ms)
@@ -95,16 +112,15 @@ int pthread_cond_timedwait(pthread_cond_t *restrict cond,
95112
pthread_mutex_t *restrict mutex,
96113
const struct timespec *restrict abstime)
97114
{
98-
// mpv uses mingw's gettimeofday() as time source too.
99-
struct timeval tv;
100-
gettimeofday(&tv, NULL);
115+
struct timespec ts;
116+
clock_gettime(CLOCK_REALTIME, &ts);
101117
DWORD timeout_ms = 0;
102-
if (abstime->tv_sec >= INT64_MAX / 10000) {
118+
if (abstime->tv_sec >= INT64_MAX / 1000) { // overflow
103119
timeout_ms = INFINITE;
104-
} else if (abstime->tv_sec >= tv.tv_sec) {
105-
long long msec = (abstime->tv_sec - tv.tv_sec) * 1000LL +
106-
abstime->tv_nsec / 1000LL / 1000LL - tv.tv_usec / 1000LL;
107-
if (msec > INT_MAX) {
120+
} else if (abstime->tv_sec >= ts.tv_sec) {
121+
int64_t msec = (abstime->tv_sec - ts.tv_sec) * INT64_C(1000) +
122+
(abstime->tv_nsec - ts.tv_nsec) / INT64_C(10000000);
123+
if (msec > ULONG_MAX) {
108124
timeout_ms = INFINITE;
109125
} else if (msec > 0) {
110126
timeout_ms = msec;

0 commit comments

Comments
 (0)