>From 7f4891ee288a6b36828ccf23f63396d35925311e Mon Sep 17 00:00:00 2001 From: Craig Ringer Date: Thu, 18 Sep 2014 23:02:14 +0800 Subject: [PATCH 2/2] Use GetSystemTimePreciseAsFileTime when available This will cause PostgreSQL on Windows 8 or Windows Server 2012 to obtain high-resolution timestamps while allowing the same binaries to run without problems on older releases. --- src/backend/main/main.c | 6 ++++++ src/include/port.h | 2 ++ src/port/gettimeofday.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/backend/main/main.c b/src/backend/main/main.c index c1116e0..6ddf147 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -259,6 +259,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 9f8465e..4f8af0a 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 73ec406..63c3a79 100644 --- a/src/port/gettimeofday.c +++ b/src/port/gettimeofday.c @@ -30,14 +30,64 @@ #include +#ifndef FRONTEND +#include +#endif + /* FILETIME of Jan 1 1970 00:00:00. */ static const unsigned __int64 epoch = UINT64CONST(116444736000000000); /* + * 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")), + "GetSystemRimePreciseAsFileTime"); + if (pg_get_system_time == NULL) + { + DWORD errcode = GetLastError(); +#ifndef FRONTEND + if (errcode != ERROR_PROC_NOT_FOUND) + { + elog(DEBUG1, "GetProcAddress(\"GetSystemRimePreciseAsFileTime\") on kernel32.dll failed with error code %d not expected ERROR_PROC_NOT_FOUND(127)", errcode); + } +#endif + 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 @@ -46,7 +96,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; -- 1.9.3