#define FILETIME_UNITS_PER_SEC 10000000L
#define FILETIME_UNITS_PER_USEC 10
+/*
+ * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a
+ * signature, so we can just store a pointer to whichever we find. This
+ * is the pointer's type.
+ */
+typedef VOID (WINAPI *PgGetSystemTimeFn)(LPFILETIME);
+
+/* Storage for the function we pick at runtime */
+static PgGetSystemTimeFn pg_get_system_time = NULL;
+
+/*
+ * During backend startup, determine if GetSystemTimePreciseAsFileTime is
+ * available and use it; if not, fall back to GetSystemTimeAsFileTime.
+ */
+void
+init_win32_gettimeofday(void)
+{
+ /*
+ * Because it's guaranteed that kernel32.dll will be linked into our
+ * address space already, we don't need to LoadLibrary it and worry about
+ * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper.
+ *
+ * We'll just look up the address of GetSystemTimePreciseAsFileTime if
+ * present.
+ *
+ * While we could look up the Windows version and skip this on Windows
+ * versions below Windows 8 / Windows Server 2012 there isn't much point,
+ * and determining the windows version is its self somewhat Windows version
+ * and development SDK specific...
+ */
+ pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress(
+ GetModuleHandle(TEXT("kernel32.dll")),
+ "GetSystemTimePreciseAsFileTime");
+ if (pg_get_system_time == NULL)
+ {
+ /*
+ * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if
+ * the function isn't present. No other error should occur.
+ *
+ * It's too early in startup to elog(...) if we get some unexpected
+ * error, and not serious enough to warrant a fprintf to stderr about
+ * it or save the error and report it later. So silently fall back to
+ * GetSystemTimeAsFileTime irrespective of why the failure occurred.
+ */
+ pg_get_system_time = &GetSystemTimeAsFileTime;
+ }
+
+}
+
/*
* timezone information is stored outside the kernel so tzp isn't used anymore.
*
- * Note: this function is not for Win32 high precision timing purpose. See
+ * Note: this function is not for Win32 high precision timing purposes. See
* elapsed_time().
*/
int
FILETIME file_time;
ULARGE_INTEGER ularge;
- GetSystemTimeAsFileTime(&file_time);
+ (*pg_get_system_time)(&file_time);
ularge.LowPart = file_time.dwLowDateTime;
ularge.HighPart = file_time.dwHighDateTime;