From: Dave Hart Date: Tue, 13 Mar 2012 09:02:35 +0000 (+0000) Subject: Use GetSystemTimePreciseAsFileTime() on Windows 8. X-Git-Tag: NTP_4_2_7P264~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=283fe525454a12b2aa9522f15ce6e3325ee76f93;p=thirdparty%2Fntp.git Use GetSystemTimePreciseAsFileTime() on Windows 8. bk: 4f5f0d2bmWTxvKgcxQTYTtlfDp3j8g --- diff --git a/ChangeLog b/ChangeLog index 9b0dda79e..78cd74ef8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +* Use GetSystemTimePreciseAsFileTime() on Windows 8. (4.2.7p263) 2012/03/13 Released by Harlan Stenn * [Bug 2156] clock instability with LOCAL driver, from Miroslav Lichvar. * [Bug 2159] Windows ntpd using leapfile erroneous leap second 20120401. diff --git a/include/ntp_fp.h b/include/ntp_fp.h index bb58bf1f8..aca5d3498 100644 --- a/include/ntp_fp.h +++ b/include/ntp_fp.h @@ -404,6 +404,8 @@ extern CRITICAL_SECTION get_systime_cs; EnterCriticalSection(&get_systime_cs) # define LEAVE_GET_SYSTIME_CRITSEC() \ LeaveCriticalSection(&get_systime_cs) +# define INIT_WIN_PRECISE_TIME() \ + init_win_precise_time() #else /* !SYS_WINNT follows */ # define INIT_GET_SYSTIME_CRITSEC() \ do {} while (FALSE) @@ -411,6 +413,8 @@ extern CRITICAL_SECTION get_systime_cs; do {} while (FALSE) # define LEAVE_GET_SYSTIME_CRITSEC() \ do {} while (FALSE) +# define INIT_WIN_PRECISE_TIME() \ + do {} while (FALSE) #endif #endif /* NTP_FP_H */ diff --git a/libntp/systime.c b/libntp/systime.c index fbe403b98..b98bb7258 100644 --- a/libntp/systime.c +++ b/libntp/systime.c @@ -105,6 +105,7 @@ void init_systime(void) { INIT_GET_SYSTIME_CRITSEC(); + INIT_WIN_PRECISE_TIME(); DONE_SYSTIME_INIT(); } diff --git a/ports/winnt/include/clockstuff.h b/ports/winnt/include/clockstuff.h index 1feffe493..3c1100b49 100644 --- a/ports/winnt/include/clockstuff.h +++ b/ports/winnt/include/clockstuff.h @@ -35,8 +35,9 @@ enum { * either GetSystemTimeAsFileTime provided by Windows * or ntpd's interpolating replacement. */ -typedef void (WINAPI *PGSTAFT)(LPFILETIME pft); +typedef void (WINAPI *PGSTAFT)(LPFILETIME pftResult); extern PGSTAFT get_sys_time_as_filetime; +extern PGSTAFT pGetSystemTimePreciseAsFileTime; void lock_thread_to_processor(HANDLE); diff --git a/ports/winnt/include/sys/time.h b/ports/winnt/include/sys/time.h index 3d7cadc05..b4489170b 100644 --- a/ports/winnt/include/sys/time.h +++ b/ports/winnt/include/sys/time.h @@ -20,5 +20,6 @@ typedef struct timespec { extern int getclock(int, struct timespec *ts); extern int gettimeofday(struct timeval *, void *); extern int settimeofday(struct timeval *); +extern void init_win_precise_time(void); #endif /* SYS_TIME_H */ diff --git a/ports/winnt/libntp/getclock.c b/ports/winnt/libntp/getclock.c index c5666dfc3..68496bd53 100644 --- a/ports/winnt/libntp/getclock.c +++ b/ports/winnt/libntp/getclock.c @@ -13,6 +13,8 @@ * via the pointer get_sys_time_as_filetime. */ PGSTAFT get_sys_time_as_filetime; +PGSTAFT pGetSystemTimePreciseAsFileTime; + int getclock( @@ -26,18 +28,11 @@ getclock( } uNow; if (clktyp != TIMEOFDAY) { -#ifdef DEBUG - if (debug) { - printf("getclock() supports only TIMEOFDAY clktyp\n"); - } -#endif + TRACE(1, ("getclock() supports only TIMEOFDAY clktyp\n")); errno = EINVAL; return -1; } - if (! get_sys_time_as_filetime) - get_sys_time_as_filetime = GetSystemTimeAsFileTime; - (*get_sys_time_as_filetime)(&uNow.ft); /* @@ -49,3 +44,20 @@ getclock( return 0; } + + +void +init_win_precise_time(void) +{ + HANDLE hDll; + FARPROC pfn; + + hDll = LoadLibrary("kernel32"); + pfn = GetProcAddress(hDll, "GetSystemTimePreciseAsFileTime"); + if (NULL != pfn) { + pGetSystemTimePreciseAsFileTime = (PGSTAFT)pfn; + get_sys_time_as_filetime = pGetSystemTimePreciseAsFileTime; + } else { + get_sys_time_as_filetime = &GetSystemTimeAsFileTime; + } +} diff --git a/ports/winnt/ntpd/nt_clockstuff.c b/ports/winnt/ntpd/nt_clockstuff.c index f52d0e1fb..fd6f6c35e 100644 --- a/ports/winnt/ntpd/nt_clockstuff.c +++ b/ports/winnt/ntpd/nt_clockstuff.c @@ -189,7 +189,7 @@ static int lock_interp_threads = -1; * ppm_per_adjust_unit is parts per million effect on the OS * clock per slewing adjustment unit per second. Per haps. */ -static DOUBLE ppm_per_adjust_unit = 0.0; +static DOUBLE ppm_per_adjust_unit; /* * wintickadj emulates the functionality provided by unix tickadj, @@ -689,34 +689,6 @@ init_winnt_time(void) if (-1 == setpriority(PRIO_PROCESS, 0, NTP_PRIO)) exit(-1); - /* - * before we start looking at clock period, do any multimedia - * timer manipulation requested via -M option. - */ - if (modify_mm_timer) { - if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) { - wTimerRes = min(max(tc.wPeriodMin, MM_TIMER_INTV), tc.wPeriodMax); - timeBeginPeriod(wTimerRes); - atexit(atexit_revert_mm_timer); - - msyslog(LOG_INFO, "MM timer resolution: %u..%u msec, set to %u msec", - tc.wPeriodMin, tc.wPeriodMax, wTimerRes ); - } else { - msyslog(LOG_ERR, "Multimedia timer unavailable"); - } - } - - /* get the performance counter ticks per second */ - if (!QueryPerformanceFrequency(&Freq) || !Freq.QuadPart) { - msyslog(LOG_ERR, "QueryPerformanceFrequency failed: %m\n"); - exit(-1); - } - - NomPerfCtrFreq = PerfCtrFreq = Freq.QuadPart; - msyslog(LOG_INFO, - "Performance counter frequency %.3f MHz", - PerfCtrFreq / 1e6); - /* Determine the existing system time slewing */ if (!GetSystemTimeAdjustment(&adjclockperiod, &clockperiod, &noslew)) { msyslog(LOG_ERR, "GetSystemTimeAdjustment failed: %m\n"); @@ -747,6 +719,58 @@ init_winnt_time(void) */ ppm_per_adjust_unit = 1e6 / clockperiod; + pch = getenv("NTPD_TICKADJ_PPM"); + if (pch != NULL && 1 == sscanf(pch, "%lf", &adjppm)) { + rawadj = adjppm / ppm_per_adjust_unit; + rawadj += (rawadj < 0) + ? -0.5 + : 0.5; + wintickadj = (long)rawadj; + msyslog(LOG_INFO, + "Using NTPD_TICKADJ_PPM %+g ppm (%+ld)", + adjppm, wintickadj); + } + + /* get the performance counter ticks per second */ + if (!QueryPerformanceFrequency(&Freq) || !Freq.QuadPart) { + msyslog(LOG_ERR, "QueryPerformanceFrequency failed: %m\n"); + exit(-1); + } + + NomPerfCtrFreq = PerfCtrFreq = Freq.QuadPart; + msyslog(LOG_INFO, + "Performance counter frequency %.3f MHz", + PerfCtrFreq / 1e6); + + /* + * With a precise system clock, our interpolation decision is + * a slam dunk. + */ + if (NULL != pGetSystemTimePreciseAsFileTime) { + winnt_use_interpolation = FALSE; + winnt_time_initialized = TRUE; + + return; + } + + /* + * Implement any multimedia timer manipulation requested via -M + * option. This is rumored to be unneeded on Win8 with the + * introduction of the precise (interpolated) system clock. + */ + if (modify_mm_timer) { + if (timeGetDevCaps(&tc, sizeof(tc)) == TIMERR_NOERROR) { + wTimerRes = min(max(tc.wPeriodMin, MM_TIMER_INTV), tc.wPeriodMax); + timeBeginPeriod(wTimerRes); + atexit(atexit_revert_mm_timer); + + msyslog(LOG_INFO, "MM timer resolution: %u..%u msec, set to %u msec", + tc.wPeriodMin, tc.wPeriodMax, wTimerRes ); + } else { + msyslog(LOG_ERR, "Multimedia timer unavailable"); + } + } + /* * Spin on GetSystemTimeAsFileTime to determine its * granularity. Prior to Windows Vista this is @@ -764,18 +788,6 @@ init_winnt_time(void) "Windows clock precision %.3f msec, min. slew %.3f ppm/s", os_clock_precision / 1e4, ppm_per_adjust_unit); - pch = getenv("NTPD_TICKADJ_PPM"); - if (pch != NULL && 1 == sscanf(pch, "%lf", &adjppm)) { - rawadj = adjppm / ppm_per_adjust_unit; - rawadj += (rawadj < 0) - ? -0.5 - : 0.5; - wintickadj = (long)rawadj; - msyslog(LOG_INFO, - "Using NTPD_TICKADJ_PPM %+g ppm (%+ld)", - adjppm, wintickadj); - } - winnt_time_initialized = TRUE; choose_interp_counter(); @@ -1199,9 +1211,10 @@ ntp_timestamp_from_counter( ULONGLONG Counterstamp ) { -#ifdef DEBUG FT_ULL Now; -#endif + FT_ULL Ctr; + LONGLONG CtrDelta; + double seconds; ULONGLONG InterpTimestamp; if (winnt_use_interpolation) { @@ -1216,7 +1229,7 @@ ntp_timestamp_from_counter( #ifdef DEBUG /* sanity check timestamp is within 1 minute of now */ GetSystemTimeAsFileTime(&Now.ft); - Now.ll -= InterpTimestamp; + Now.ull -= InterpTimestamp; if (debug && Now.ll > 60 * HECTONANOSECONDS || Now.ll < -60 * HECTONANOSECONDS) { @@ -1232,16 +1245,28 @@ ntp_timestamp_from_counter( } #endif } else { /* ! winnt_use_interpolation */ - /* have to simply use the driver's system time timestamp */ - InterpTimestamp = Timestamp; + if (NULL != pGetSystemTimePreciseAsFileTime) { + QueryPerformanceCounter(&Ctr.li); + (*pGetSystemTimePreciseAsFileTime)(&Now.ft); + CtrDelta = Ctr.ull - Counterstamp; + seconds = (double)CtrDelta / PerfCtrFreq; + InterpTimestamp = Now.ull - + (ULONGLONG)(seconds * HECTONANOSECONDS); + } else { + /* have to simply use the driver's system time timestamp */ + InterpTimestamp = Timestamp; + GetSystemTimeAsFileTime(&Now.ft); + } #ifdef DEBUG /* sanity check timestamp is within 1 minute of now */ - GetSystemTimeAsFileTime(&Now.ft); - Now.ll -= InterpTimestamp; + Now.ull -= InterpTimestamp; if (debug && Now.ll > 60 * HECTONANOSECONDS || Now.ll < -60 * HECTONANOSECONDS) { - DPRINTF(1, ("ntp_timestamp_from_counter serial driver system time %.6fs from current\n", + DPRINTF(1, ("ntp_timestamp_from_counter serial driver %s time %.6fs from current\n", + (NULL == pGetSystemTimePreciseAsFileTime) + ? "system" + : "counter", Now.ll / (double)HECTONANOSECONDS)); msyslog(LOG_ERR, "ntp_timestamp_from_counter serial driver system time %.6fs from current\n", diff --git a/util/ntp-keygen.c b/util/ntp-keygen.c index 2772707ae..65e2d9ac3 100644 --- a/util/ntp-keygen.c +++ b/util/ntp-keygen.c @@ -219,7 +219,7 @@ symlink( if (!tried) { tried = TRUE; - hDll = LoadLibrary("kernel32.dll"); + hDll = LoadLibrary("kernel32"); pfn = GetProcAddress(hDll, "CreateHardLinkA"); pCreateHardLinkA = (PCREATEHARDLINKA)pfn; }