Skip to content

Commit f199239

Browse files
Roman ZippelLinus Torvalds
authored andcommitted
[PATCH] ntp: convert to the NTP4 reference model
This converts the kernel ntp model into a model which matches the nanokernel reference implementations. The previous patches already increased the resolution and precision of the computations, so that this conversion becomes quite simple. <[email protected]> explains: The original NTP kernel interface was defined in units of microseconds. That's what Linux implements. As computers have gotten faster and can now split microseconds easily, a new kernel interface using nanosecond units was defined ("the nanokernel", confusing as that name is to OS hackers), and there's an STA_NANO bit in the adjtimex() status field to tell the application which units it's using. The current ntpd supports both, but Linux loses some possible timing resolution because of quantization effects, and the ntpd hackers would really like to be able to drop the backwards compatibility code. Ulrich Windl has been maintaining a patch set to do the conversion for years, but it's hard to keep in sync. Signed-off-by: Roman Zippel <[email protected]> Cc: john stultz <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 04b617e commit f199239

File tree

2 files changed

+24
-38
lines changed

2 files changed

+24
-38
lines changed

include/linux/timex.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,9 @@
6969
* zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
7070
* respectively.
7171
*/
72-
#define SHIFT_KG 6 /* phase factor (shift) */
73-
#define SHIFT_KF 16 /* PLL frequency factor (shift) */
74-
#define SHIFT_KH 2 /* FLL frequency factor (shift) */
75-
#define MAXTC 6 /* maximum time constant (shift) */
72+
#define SHIFT_PLL 4 /* PLL frequency factor (shift) */
73+
#define SHIFT_FLL 2 /* FLL frequency factor (shift) */
74+
#define MAXTC 10 /* maximum time constant (shift) */
7675

7776
/*
7877
* The SHIFT_SCALE define establishes the decimal point of the time_phase
@@ -97,8 +96,8 @@
9796
#define MAXPHASE 512000L /* max phase error (us) */
9897
#define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */
9998
#define MAXFREQ_NSEC (512000L << SHIFT_NSEC) /* max frequency error (ppb) */
100-
#define MINSEC 16L /* min interval between updates (s) */
101-
#define MAXSEC 1200L /* max interval between updates (s) */
99+
#define MINSEC 256 /* min interval between updates (s) */
100+
#define MAXSEC 2048 /* max interval between updates (s) */
102101
#define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */
103102

104103
/*

kernel/time/ntp.c

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,11 @@ void second_overflow(void)
145145
}
146146

147147
/*
148-
* Compute the phase adjustment for the next second. In PLL mode, the
149-
* offset is reduced by a fixed factor times the time constant. In FLL
150-
* mode the offset is used directly. In either mode, the maximum phase
151-
* adjustment for each second is clamped so as to spread the adjustment
152-
* over not more than the number of seconds between updates.
148+
* Compute the phase adjustment for the next second. The offset is
149+
* reduced by a fixed factor times the time constant.
153150
*/
154151
tick_length = tick_length_base;
155-
time_adj = time_offset;
156-
if (!(time_status & STA_FLL))
157-
time_adj = shift_right(time_adj, SHIFT_KG + time_constant);
158-
time_adj = min(time_adj, -((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
159-
time_adj = max(time_adj, ((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
152+
time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
160153
time_offset -= time_adj;
161154
tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
162155

@@ -200,7 +193,7 @@ void __attribute__ ((weak)) notify_arch_cmos_timer(void)
200193
int do_adjtimex(struct timex *txc)
201194
{
202195
long ltemp, mtemp, save_adjust;
203-
s64 freq_adj;
196+
s64 freq_adj, temp64;
204197
int result;
205198

206199
/* In order to modify anything, you gotta be super-user! */
@@ -270,7 +263,7 @@ int do_adjtimex(struct timex *txc)
270263
result = -EINVAL;
271264
goto leave;
272265
}
273-
time_constant = txc->constant;
266+
time_constant = min(txc->constant + 4, (long)MAXTC);
274267
}
275268

276269
if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
@@ -298,26 +291,20 @@ int do_adjtimex(struct timex *txc)
298291
time_reftime = xtime.tv_sec;
299292
mtemp = xtime.tv_sec - time_reftime;
300293
time_reftime = xtime.tv_sec;
301-
freq_adj = 0;
302-
if (time_status & STA_FLL) {
303-
if (mtemp >= MINSEC) {
304-
freq_adj = (s64)time_offset << (SHIFT_NSEC - SHIFT_KH);
305-
if (time_offset < 0) {
306-
freq_adj = -freq_adj;
307-
do_div(freq_adj, mtemp);
308-
freq_adj = -freq_adj;
309-
} else
310-
do_div(freq_adj, mtemp);
311-
} else /* calibration interval too short (p. 12) */
312-
result = TIME_ERROR;
313-
} else { /* PLL mode */
314-
if (mtemp < MAXSEC) {
315-
freq_adj = (s64)ltemp * mtemp;
316-
freq_adj = shift_right(freq_adj,(time_constant +
317-
time_constant +
318-
SHIFT_KF - SHIFT_NSEC));
319-
} else /* calibration interval too long (p. 12) */
320-
result = TIME_ERROR;
294+
295+
freq_adj = (s64)time_offset * mtemp;
296+
freq_adj = shift_right(freq_adj, time_constant * 2 +
297+
(SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
298+
if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
299+
temp64 = (s64)time_offset << (SHIFT_NSEC - SHIFT_FLL);
300+
if (time_offset < 0) {
301+
temp64 = -temp64;
302+
do_div(temp64, mtemp);
303+
freq_adj -= temp64;
304+
} else {
305+
do_div(temp64, mtemp);
306+
freq_adj += temp64;
307+
}
321308
}
322309
freq_adj += time_freq;
323310
freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);

0 commit comments

Comments
 (0)