bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gettimeofday: improve for native Windows


From: Bruno Haible
Subject: gettimeofday: improve for native Windows
Date: Sun, 30 Apr 2017 19:42:06 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-75-generic; KDE/5.18.0; x86_64; ; )

gettimeofday should provide the same time resolution as utime.


2017-04-30  Bruno Haible  <address@hidden>

        gettimeofday: Provide higher resolution on native Windows.
        * lib/gettimeofday.c: Don't include <sys/timeb.h>.
        (GetSystemTimePreciseAsFileTimeFuncType): New variable.
        (initialize): Initialize it.
        (gettimeofday) [WINDOWS_NATIVE]: Use it, and convert from FILETIME to
        'struct timeval'. Don't use _ftime().
        * m4/gettimeofday.m4 (gl_PREREQ_GETTIMEOFDAY): Don't test for
        <sys/timeb.h> and _ftime.

diff --git a/lib/gettimeofday.c b/lib/gettimeofday.c
index d6117bd..a4a71a7 100644
--- a/lib/gettimeofday.c
+++ b/lib/gettimeofday.c
@@ -24,8 +24,9 @@
 
 #include <time.h>
 
-#if HAVE_SYS_TIMEB_H
-# include <sys/timeb.h>
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WINDOWS_NATIVE
+# include <windows.h>
 #endif
 
 #if GETTIMEOFDAY_CLOBBERS_LOCALTIME || TZSET_CLOBBERS_LOCALTIME
@@ -92,6 +93,28 @@ rpl_tzset (void)
   tzset ();
   *localtime_buffer_addr = save;
 }
+
+#endif
+
+#ifdef WINDOWS_NATIVE
+
+/* GetSystemTimePreciseAsFileTime was introduced only in Windows 8.  */
+typedef void (WINAPI * GetSystemTimePreciseAsFileTimeFuncType) (FILETIME 
*lpTime);
+static GetSystemTimePreciseAsFileTimeFuncType 
GetSystemTimePreciseAsFileTimeFunc = NULL;
+static BOOL initialized = FALSE;
+
+static void
+initialize (void)
+{
+  HMODULE kernel32 = LoadLibrary ("kernel32.dll");
+  if (kernel32 != NULL)
+    {
+      GetSystemTimePreciseAsFileTimeFunc =
+       (GetSystemTimePreciseAsFileTimeFuncType) GetProcAddress (kernel32, 
"GetSystemTimePreciseAsFileTime");
+    }
+  initialized = TRUE;
+}
+
 #endif
 
 /* This is a wrapper for gettimeofday.  It is used only on systems
@@ -130,12 +153,35 @@ gettimeofday (struct timeval *restrict tv, void *restrict 
tz)
 
 #else
 
-# if HAVE__FTIME
-
-  struct _timeb timebuf;
-  _ftime (&timebuf);
-  tv->tv_sec = timebuf.time;
-  tv->tv_usec = timebuf.millitm * 1000;
+# ifdef WINDOWS_NATIVE
+
+  /* On native Windows, there are two ways to get the current time:
+     GetSystemTimeAsFileTime
+     <https://msdn.microsoft.com/en-us/library/ms724397.aspx>
+     or
+     GetSystemTimePreciseAsFileTime
+     <https://msdn.microsoft.com/en-us/library/hh706895.aspx>.  */
+  FILETIME current_time;
+
+  if (!initialized)
+    initialize ();
+  if (GetSystemTimePreciseAsFileTimeFunc != NULL)
+    GetSystemTimePreciseAsFileTimeFunc (&current_time);
+  else
+    GetSystemTimeAsFileTime (&current_time);
+
+  /* Convert from FILETIME to 'struct timeval'.  */
+  /* FILETIME: <https://msdn.microsoft.com/en-us/library/ms724284.aspx> */
+  ULONGLONG since_1601 =
+    ((ULONGLONG) current_time.dwHighDateTime << 32)
+    | (ULONGLONG) current_time.dwLowDateTime;
+  /* Between 1601-01-01 and 1970-01-01 there were 280 normal years and 89 leap
+     years, in total 134774 days.  */
+  ULONGLONG since_1970 =
+    since_1601 - (ULONGLONG) 134774 * (ULONGLONG) 86400 * (ULONGLONG) 10000000;
+  ULONGLONG microseconds_since_1970 = since_1970 / (ULONGLONG) 10;
+  tv->tv_sec = microseconds_since_1970 / (ULONGLONG) 1000000;
+  tv->tv_usec = microseconds_since_1970 % (ULONGLONG) 1000000;
 
 # else
 
diff --git a/m4/gettimeofday.m4 b/m4/gettimeofday.m4
index 4f501e5..742b6c9 100644
--- a/m4/gettimeofday.m4
+++ b/m4/gettimeofday.m4
@@ -1,4 +1,4 @@
-# serial 21
+# serial 22
 
 # Copyright (C) 2001-2003, 2005, 2007, 2009-2017 Free Software Foundation, Inc.
 # This file is free software; the Free Software Foundation
@@ -132,7 +132,4 @@ AC_DEFUN([gl_GETTIMEOFDAY_REPLACE_LOCALTIME], [
 ])
 
 # Prerequisites of lib/gettimeofday.c.
-AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [
-  AC_CHECK_HEADERS([sys/timeb.h])
-  AC_CHECK_FUNCS([_ftime])
-])
+AC_DEFUN([gl_PREREQ_GETTIMEOFDAY], [:])




reply via email to

[Prev in Thread] Current Thread [Next in Thread]