changeset 38514:869cbe085e12

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.
author Bruno Haible <bruno@clisp.org>
date Sun, 30 Apr 2017 12:15:08 +0200
parents 922850c36342
children 20e94b6fcdaa
files ChangeLog lib/gettimeofday.c m4/gettimeofday.m4
diffstat 3 files changed, 66 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Apr 30 11:38:25 2017 +0200
+++ b/ChangeLog	Sun Apr 30 12:15:08 2017 +0200
@@ -1,3 +1,14 @@
+2017-04-30  Bruno Haible  <bruno@clisp.org>
+
+	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.
+
 2017-04-30  Bruno Haible  <bruno@clisp.org>
 
 	Document the problem with the Cygwin environment variable TZ.
--- a/lib/gettimeofday.c	Sun Apr 30 11:38:25 2017 +0200
+++ b/lib/gettimeofday.c	Sun Apr 30 12:15:08 2017 +0200
@@ -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 @@
   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 @@
 
 #else
 
-# if HAVE__FTIME
+# 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;
 
-  struct _timeb timebuf;
-  _ftime (&timebuf);
-  tv->tv_sec = timebuf.time;
-  tv->tv_usec = timebuf.millitm * 1000;
+  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
 
--- a/m4/gettimeofday.m4	Sun Apr 30 11:38:25 2017 +0200
+++ b/m4/gettimeofday.m4	Sun Apr 30 12:15:08 2017 +0200
@@ -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 @@
 ])
 
 # 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], [:])