winpthreads: Increase precision of CLOCK_REALTIME, add CLOCK_REALTIME_COARSE. Use GetSystemTimePreciseAsFileTime() for CLOCK_REALTIME if available. Always use GetSystemTimeAsFileTime() for CLOCK_REALTIME_COARSE. Signed-off-by: Christian Franke <christian.franke@t-online.de> Signed-off-by: Liu Hao <lh_mouse@126.com>
diff --git a/mingw-w64-libraries/winpthreads/include/pthread_time.h b/mingw-w64-libraries/winpthreads/include/pthread_time.h index 7a7538c..7818b11 100644 --- a/mingw-w64-libraries/winpthreads/include/pthread_time.h +++ b/mingw-w64-libraries/winpthreads/include/pthread_time.h
@@ -70,6 +70,10 @@ #define CLOCK_THREAD_CPUTIME_ID 3 #endif +#ifndef CLOCK_REALTIME_COARSE +#define CLOCK_REALTIME_COARSE 4 +#endif + #ifdef __cplusplus extern "C" { #endif
diff --git a/mingw-w64-libraries/winpthreads/src/clock.c b/mingw-w64-libraries/winpthreads/src/clock.c index 5ad710b..ba983c9 100644 --- a/mingw-w64-libraries/winpthreads/src/clock.c +++ b/mingw-w64-libraries/winpthreads/src/clock.c
@@ -31,6 +31,30 @@ return 0; } +typedef void (WINAPI * GetSystemTimeAsFileTime_t)(LPFILETIME); +static GetSystemTimeAsFileTime_t GetSystemTimeAsFileTime_p /* = 0 */; + +static GetSystemTimeAsFileTime_t try_load_GetSystemPreciseTimeAsFileTime() +{ + /* Use GetSystemTimePreciseAsFileTime() if available (Windows 8 or later) */ + GetSystemTimeAsFileTime_t get_time = (GetSystemTimeAsFileTime_t)(intptr_t)GetProcAddress( + GetModuleHandle ("kernel32.dll"), + "GetSystemTimePreciseAsFileTime"); /* <1us precision on Windows 10 */ + if (get_time == NULL) + get_time = GetSystemTimeAsFileTime; /* >15ms precision on Windows 10 */ + __atomic_store_n(&GetSystemTimeAsFileTime_p, get_time, __ATOMIC_RELAXED); + return get_time; +} + +static WINPTHREADS_INLINE GetSystemTimeAsFileTime_t load_GetSystemTimeBestAsFileTime() +{ + GetSystemTimeAsFileTime_t get_time = + __atomic_load_n(&GetSystemTimeAsFileTime_p, __ATOMIC_RELAXED); + if (get_time == NULL) + get_time = try_load_GetSystemPreciseTimeAsFileTime(); + return get_time; +} + /** * Get the resolution of the specified clock clock_id and * stores it in the struct timespec pointed to by res. @@ -52,7 +76,13 @@ */ int clock_getres(clockid_t clock_id, struct timespec *res) { - switch(clock_id) { + clockid_t id = clock_id; + + if (id == CLOCK_REALTIME && load_GetSystemTimeBestAsFileTime() == GetSystemTimeAsFileTime) + id = CLOCK_REALTIME_COARSE; /* GetSystemTimePreciseAsFileTime() not available */ + + switch(id) { + case CLOCK_REALTIME: case CLOCK_MONOTONIC: { LARGE_INTEGER pf; @@ -68,7 +98,7 @@ return 0; } - case CLOCK_REALTIME: + case CLOCK_REALTIME_COARSE: case CLOCK_PROCESS_CPUTIME_ID: case CLOCK_THREAD_CPUTIME_ID: { @@ -118,6 +148,16 @@ switch(clock_id) { case CLOCK_REALTIME: { + load_GetSystemTimeBestAsFileTime()(&ct.ft); + t = ct.u64 - DELTA_EPOCH_IN_100NS; + tp->tv_sec = t / POW10_7; + tp->tv_nsec = ((int) (t % POW10_7)) * 100; + + return 0; + } + + case CLOCK_REALTIME_COARSE: + { GetSystemTimeAsFileTime(&ct.ft); t = ct.u64 - DELTA_EPOCH_IN_100NS; tp->tv_sec = t / POW10_7;