aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/main/main.c6
-rw-r--r--src/include/port.h2
-rw-r--r--src/port/gettimeofday.c53
3 files changed, 59 insertions, 2 deletions
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index c51b391199c..73c30c53543 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -260,6 +260,12 @@ startup_hacks(const char *progname)
/* In case of general protection fault, don't show GUI popup box */
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+
+#ifndef HAVE_GETTIMEOFDAY
+ /* Figure out which syscall to use to capture timestamp information */
+ init_win32_gettimeofday();
+#endif
+
}
#endif /* WIN32 */
diff --git a/src/include/port.h b/src/include/port.h
index 94a0e2fe2b4..58677ec6bdf 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -328,6 +328,8 @@ extern FILE *pgwin32_popen(const char *command, const char *type);
#ifndef HAVE_GETTIMEOFDAY
/* Last parameter not used */
extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
+/* On windows we need to call some backend start setup for accurate timing */
+extern void init_win32_gettimeofday(void);
#endif
#else /* !WIN32 */
diff --git a/src/port/gettimeofday.c b/src/port/gettimeofday.c
index ecc0b4dd704..eabf161e04a 100644
--- a/src/port/gettimeofday.c
+++ b/src/port/gettimeofday.c
@@ -42,9 +42,58 @@ static const unsigned __int64 epoch = UINT64CONST(116444736000000000);
#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
@@ -53,7 +102,7 @@ gettimeofday(struct timeval * tp, struct timezone * tzp)
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;