master
 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
15int getntptimeofday (struct timespec *, struct timezone *);
16
17int 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
68int __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
79int __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}