From e147f2f11e1bc208db9053fa1df05d9b4857a545 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 22 May 2014 16:28:20 +0200 Subject: [PATCH] sys: drop frequency scaling in Linux driver Since the kernel USER_HZ constant was introduced and the internal HZ can't be reliably detected in user-space, the frequency scaling constant used with older kernels is just a random guess. Remove the scaling completely and let the closed loop compensate for the error. To prevent thrashing between two states when the system's frequency error is close to a multiple of USER_HZ, stick to the current tick value if it's next to the new required tick. This is used only on archs where USER_HZ is 100 as the frequency adjustment is limited to 500 ppm. The linux_hz and linux_freq_scale directives are no longer supported, but allowed by the config parser. --- chrony.texi.in | 34 ------------ conf.c | 32 +---------- conf.h | 2 - sys_linux.c | 141 +++++++++++++++---------------------------------- 4 files changed, 45 insertions(+), 164 deletions(-) diff --git a/chrony.texi.in b/chrony.texi.in index f1e938d..6503ca8 100644 --- a/chrony.texi.in +++ b/chrony.texi.in @@ -1141,8 +1141,6 @@ the configuration file is ignored. * initstepslew directive:: Trim the system clock on boot-up * keyfile directive:: Specify location of file containing keys * leapsectz directive:: Read leap second data from tz database -* linux_freq_scale directive:: Define a non-standard value to compensate the kernel frequency bias -* linux_hz directive:: Define a non-standard value of the kernel USER_HZ constant * local directive:: Allow unsynchronised machine to act as server * lock_all directive:: Require that chronyd be locked into RAM * log directive:: Make daemon log certain sets of information @@ -1818,38 +1816,6 @@ $ TZ=right/UTC date -d 'Dec 31 2008 23:59:60' Wed Dec 31 23:59:60 UTC 2008 @end example -@c }}} -@c {{{ linux_freq_scale -@node linux_freq_scale directive -@subsection linux_freq_scale -(This option only applies to Linux). - -This option sets a scale factor needed to control the frequency of the clock by -the @code{adjtimex()} system call exactly. By default, the value is determined -by the version of the running kernel. In recent kernels it is always 1.0 (i.e. -no scaling is needed). - -An example of the command is - -@example -linux_freq_scale 0.99902439 -@end example -@c }}} -@c {{{ linux_hz -@node linux_hz directive -@subsection linux_hz -(This option only applies to Linux). - -This option defines the value of the kernel @code{USER_HZ} constant, which is -needed to use the @code{adjtimex()} system call correctly. By default, its -value is determined from the running kernel automatically and there should -rarely be a need to use this option. - -An example of the command is - -@example -linux_hz 100 -@end example @c }}} @c {{{ local @node local directive diff --git a/conf.c b/conf.c index 26fd605..50ed760 100644 --- a/conf.c +++ b/conf.c @@ -187,16 +187,6 @@ static char *tempcomp_file = NULL; static double tempcomp_interval; static double tempcomp_T0, tempcomp_k0, tempcomp_k1, tempcomp_k2; -/* Boolean for whether the Linux HZ value has been overridden, and the - * new value. */ -static int set_linux_hz = 0; -static int linux_hz; - -/* Boolean for whether the Linux frequency scaling value (i.e. the one that's - * approx (1<> - (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE); - - causes the adjtimex 'freq' value to be divided down by 1< only 0.125% error (p. 14) - * - if (time_adj < 0) - time_adj -= (-time_adj >> 2) + (-time_adj >> 5); - else - time_adj += (time_adj >> 2) + (time_adj >> 5); -#endif - - Special case that later. - */ - if (uname(&uts) < 0) { LOG_FATAL(LOGF_SysLinux, "Cannot uname(2) to get kernel version, sorry."); } @@ -345,17 +302,11 @@ get_version_specific_details(void) LOG_FATAL(LOGF_SysLinux, "Kernel version not supported, sorry."); } - if (kernelvercmp(major, minor, patch, 2, 6, 27) < 0) { - freq_scale = (hz == 100) ? (128.0 / 128.125) : basic_freq_scale; - } else { - /* These don't seem to need scaling */ - freq_scale = 1.0; - - if (kernelvercmp(major, minor, patch, 2, 6, 33) < 0) { - /* Tickless kernels before 2.6.33 accumulated ticks only in - half-second intervals */ - tick_update_hz = 2; - } + if (kernelvercmp(major, minor, patch, 2, 6, 27) >= 0 && + kernelvercmp(major, minor, patch, 2, 6, 33) < 0) { + /* Tickless kernels before 2.6.33 accumulated ticks only in + half-second intervals */ + tick_update_hz = 2; } /* ADJ_SETOFFSET support */ @@ -365,14 +316,8 @@ get_version_specific_details(void) have_setoffset = 1; } - /* Override freq_scale if it appears in conf file */ - CNF_GetLinuxFreqScale(&set_config_freq_scale, &config_freq_scale); - if (set_config_freq_scale) { - freq_scale = config_freq_scale; - } - - DEBUG_LOG(LOGF_SysLinux, "hz=%d shift_hz=%d freq_scale=%.8f nominal_tick=%d max_tick_bias=%d", - hz, shift_hz, freq_scale, nominal_tick, max_tick_bias); + DEBUG_LOG(LOGF_SysLinux, "hz=%d nominal_tick=%d max_tick_bias=%d", + hz, nominal_tick, max_tick_bias); } /* ================================================== */