c11: Implement timespec_get on win32 properly when not available
authorYonggang Luo <luoyonggang@gmail.com>
Tue, 19 Apr 2022 16:22:24 +0000 (00:22 +0800)
committerMarge Bot <emma+marge@anholt.net>
Thu, 9 Jun 2022 17:23:34 +0000 (17:23 +0000)
Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15497>

src/c11/impl/time.c

index 7c9cf6e..8a44412 100644 (file)
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
 
-#include <assert.h>
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
+#include <windows.h>
 
 int
 timespec_get(struct timespec *ts, int base)
 {
-    assert(ts != NULL);
+/* difference between 1970 and 1601 */
+#define _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull
+/* 1 tick is 100 nanoseconds */
+#define _TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull
+    if (!ts)
+        return 0;
     if (base == TIME_UTC) {
-        ts->tv_sec = time(NULL);
-        ts->tv_nsec = 0;
+        FILETIME ft;
+        ULARGE_INTEGER date;
+        LONGLONG ticks;
+
+        GetSystemTimeAsFileTime(&ft);
+        date.HighPart = ft.dwHighDateTime;
+        date.LowPart = ft.dwLowDateTime;
+        ticks = (LONGLONG)(date.QuadPart - _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS);
+        ts->tv_sec = ticks / _TIMESPEC_IMPL_TICKS_PER_SECONDS;
+        ts->tv_nsec = (ticks % _TIMESPEC_IMPL_TICKS_PER_SECONDS) * 100;
         return base;
     }
     return 0;
+#undef _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS
+#undef _TIMESPEC_IMPL_TICKS_PER_SECONDS
 }
 
 #else