| 1 | /** |
| 2 | * This file has no copyright assigned and is placed in the Public Domain. |
| 3 | * This file is part of the mingw-w64 runtime package. |
| 4 | * No warranty is given; refer to the file DISCLAIMER.PD within this package. |
| 5 | */ |
| 6 | #include <time.h> |
| 7 | #include <sys/time.h> |
| 8 | #include <sys/timeb.h> |
| 9 | #include <errno.h> |
| 10 | #include <windows.h> |
| 11 | |
| 12 | #define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */ |
| 13 | #define HECTONANOSEC_PER_SEC 10000000ull |
| 14 | |
| 15 | int getntptimeofday (struct timespec *, struct timezone *); |
| 16 | |
| 17 | int getntptimeofday (struct timespec *tp, struct timezone *z) |
| 18 | { |
| 19 | int res = 0; |
| 20 | union { |
| 21 | unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ |
| 22 | FILETIME ft; |
| 23 | } _now; |
| 24 | TIME_ZONE_INFORMATION TimeZoneInformation; |
| 25 | DWORD tzi; |
| 26 | |
| 27 | if (z != NULL) |
| 28 | { |
| 29 | if ((tzi = GetTimeZoneInformation(&TimeZoneInformation)) != TIME_ZONE_ID_INVALID) { |
| 30 | 	z->tz_minuteswest = TimeZoneInformation.Bias; |
| 31 | 	if (tzi == TIME_ZONE_ID_DAYLIGHT) |
| 32 | 	 z->tz_dsttime = 1; |
| 33 | 	else |
| 34 | 	 z->tz_dsttime = 0; |
| 35 | } |
| 36 | else |
| 37 | { |
| 38 | 	z->tz_minuteswest = 0; |
| 39 | 	z->tz_dsttime = 0; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | if (tp != NULL) { |
| 44 | typedef void (WINAPI * GetSystemTimeAsFileTime_t)(LPFILETIME); |
| 45 | static GetSystemTimeAsFileTime_t GetSystemTimeAsFileTime_p /* = 0 */; |
| 46 | |
| 47 | /* Set function pointer during first call */ |
| 48 | GetSystemTimeAsFileTime_t get_time = |
| 49 | __atomic_load_n (&GetSystemTimeAsFileTime_p, __ATOMIC_RELAXED); |
| 50 | if (get_time == NULL) { |
| 51 | /* Use GetSystemTimePreciseAsFileTime() if available (Windows 8 or later) */ |
| 52 | get_time = (GetSystemTimeAsFileTime_t)(intptr_t) GetProcAddress ( |
| 53 | GetModuleHandle ("kernel32.dll"), |
| 54 | "GetSystemTimePreciseAsFileTime"); /* <1us precision on Windows 10 */ |
| 55 | if (get_time == NULL) |
| 56 | get_time = GetSystemTimeAsFileTime; /* >15ms precision on Windows 10 */ |
| 57 | __atomic_store_n (&GetSystemTimeAsFileTime_p, get_time, __ATOMIC_RELAXED); |
| 58 | } |
| 59 | |
| 60 | get_time (&_now.ft);	/* 100 nano-seconds since 1-1-1601 */ |
| 61 | _now.ns100 -= FILETIME_1970;	/* 100 nano-seconds since 1-1-1970 */ |
| 62 | tp->tv_sec = _now.ns100 / HECTONANOSEC_PER_SEC;	/* seconds since 1-1-1970 */ |
| 63 | tp->tv_nsec = (long) (_now.ns100 % HECTONANOSEC_PER_SEC) * 100; /* nanoseconds */ |
| 64 | } |
| 65 | return res; |
| 66 | } |
| 67 | |
| 68 | int __cdecl gettimeofday (struct timeval *p, void *z) |
| 69 | { |
| 70 | struct timespec tp; |
| 71 | |
| 72 | if (getntptimeofday (&tp, (struct timezone *) z)) |
| 73 | return -1; |
| 74 | p->tv_sec=tp.tv_sec; |
| 75 | p->tv_usec=(tp.tv_nsec/1000); |
| 76 | return 0; |
| 77 | } |
| 78 | |
| 79 | int __cdecl mingw_gettimeofday (struct timeval *p, struct timezone *z) |
| 80 | { |
| 81 | struct timespec tp; |
| 82 | |
| 83 | if (getntptimeofday (&tp, z)) |
| 84 | return -1; |
| 85 | p->tv_sec=tp.tv_sec; |
| 86 | p->tv_usec=(tp.tv_nsec/1000); |
| 87 | return 0; |
| 88 | } |