static double max_clock_error = 1.0; /* in ppm */
static double max_drift = 500000.0; /* in ppm */
static double max_slew_rate = 1e6 / 12.0; /* in ppm */
+static double clock_precision = 0.0; /* in seconds */
static SRC_AuthSelectMode authselect_mode = SRC_AUTHSELECT_MIX;
static double max_distance = 3.0;
parse_broadcast(p);
} else if (!strcasecmp(command, "clientloglimit")) {
parse_clientloglimit(p);
+ } else if (!strcasecmp(command, "clockprecision")) {
+ parse_double(p, &clock_precision);
} else if (!strcasecmp(command, "cmdallow")) {
parse_allow_deny(p, cmd_restrictions, 1);
} else if (!strcasecmp(command, "cmddeny")) {
/* ================================================== */
+double
+CNF_GetClockPrecision(void)
+{
+ return clock_precision;
+}
+
+/* ================================================== */
+
double
CNF_GetMaxDistance(void)
{
extern double CNF_GetMaxDrift(void);
extern double CNF_GetCorrectionTimeRatio(void);
extern double CNF_GetMaxSlewRate(void);
+extern double CNF_GetClockPrecision(void);
extern SRC_AuthSelectMode CNF_GetAuthSelectMode(void);
extern double CNF_GetMaxDistance(void);
=== System clock
+[[clockprecision]]*clockprecision* _precision_::
+The *clockprecision* directive specifies the precision of the system clock (in
+seconds). It is used by *chronyd* to estimate the minimum noise in NTP
+measurements and randomise low-order bits of timestamps in NTP responses. By
+default, the precision is measured on start as the minimum time to read the
+clock.
++
+The measured value works well in most cases. However, it generally
+overestimates the precision and it can be sensitive to the CPU speed, which can
+change over time to save power. In some cases with a high-precision clocksource
+(e.g. the Time Stamp Counter of the CPU) and hardware timestamping, setting the
+precision on the server to a smaller value can improve stability of clients'
+NTP measurements. The server's precision is reported on clients by the
+<<chronyc.adoc#ntpdata,*ntpdata*>> command.
++
+An example setting the precision to 8 nanoseconds is:
++
+----
+clockprecision 8e-9
+----
+
[[corrtimeratio]]*corrtimeratio* _ratio_::
When *chronyd* is slewing the system clock to correct an offset, the rate at
which it is slewing adds to the frequency error of the clock. On all supported
#define NSEC_PER_SEC 1000000000
-static void
-calculate_sys_precision(void)
+static double
+measure_clock_precision(void)
{
struct timespec ts, old_ts;
int iters, diff, best;
assert(best > 0);
- precision_quantum = 1.0e-9 * best;
-
- /* Get rounded log2 value of the measured precision */
- precision_log = 0;
- while (best < 707106781) {
- precision_log--;
- best *= 2;
- }
-
- assert(precision_log >= -30);
-
- DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
+ return 1.0e-9 * best;
}
/* ================================================== */
current_freq_ppm = 0.0;
temp_comp_ppm = 0.0;
- calculate_sys_precision();
+ precision_quantum = CNF_GetClockPrecision();
+ if (precision_quantum <= 0.0)
+ precision_quantum = measure_clock_precision();
+
+ precision_quantum = CLAMP(1.0e-9, precision_quantum, 1.0);
+ precision_log = round(log(precision_quantum) / log(2.0));
+ /* NTP code doesn't support smaller log than -30 */
+ assert(precision_log >= -30);
+
+ DEBUG_LOG("Clock precision %.9f (%d)", precision_quantum, precision_log);
/* This is the maximum allowed frequency offset in ppm, the time must
never stop or run backwards */