summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_tc.c
diff options
context:
space:
mode:
authorcheloha <cheloha@openbsd.org>2019-12-02 02:24:29 +0000
committercheloha <cheloha@openbsd.org>2019-12-02 02:24:29 +0000
commit1c733b92bb4dc807333a5780ab36f50df04fe341 (patch)
tree8fb59259eab21242d0e478aea72222024c53f54f /sys/kern/kern_tc.c
parentoutput_createtmp() remembers the true name, so output_finish() does not (diff)
downloadwireguard-openbsd-1c733b92bb4dc807333a5780ab36f50df04fe341.tar.xz
wireguard-openbsd-1c733b92bb4dc807333a5780ab36f50df04fe341.zip
tc_windup: separate timecounter.tc_freq_adj from timehands.th_adjustment
We currently mix timecounter.tc_freq_adj and timehands.th_adjtimedelta in ntp_update_second() to produce timehands.th_adjustment, our net skew. But if you set a low enough adjfreq(2) adjustment you can freeze time. This prevents ntp_update_second() from running again. So even if you then set a sane adjfreq(2) you cannot unfreeze time without rebooting. If we just reread timecounter.tc_freq_adj every time we recompute timehands.th_scale we avoid this trap. visa@ notes that this is more costly than what we currently do but that the cost itself is negligible. Intuitively, timecounter.tc_freq_adj is a constant skew and should be handled separately from timehands.th_adjtimedelta, an adjustment that we chip away at very slowly. tedu@ notes that this problem is sort-of an argument for imposing range limits on adjfreq(2) inputs. He's right, but I think we should still separate the counter adjustment from the adjtime(2) adjustment, with or without range limits. ok visa@
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r--sys/kern/kern_tc.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 2804e2ffbda..a911acc8f59 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_tc.c,v 1.51 2019/11/26 15:27:08 cheloha Exp $ */
+/* $OpenBSD: kern_tc.c,v 1.52 2019/12/02 02:24:29 cheloha Exp $ */
/*
* Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org>
@@ -477,6 +477,7 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
struct bintime bt;
struct timecounter *active_tc;
struct timehands *th, *tho;
+ int64_t counter_adjustment;
u_int64_t scale;
u_int delta, ncount, ogen;
int i;
@@ -594,7 +595,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset,
*
*/
scale = (u_int64_t)1 << 63;
- scale += (th->th_adjustment / 1024) * 2199;
+ counter_adjustment = th->th_counter->tc_freq_adj;
+ scale += ((th->th_adjustment + counter_adjustment) / 1024) * 2199;
scale /= th->th_counter->tc_frequency;
th->th_scale = scale * 2;
@@ -751,7 +753,7 @@ sysctl_tc(int *name, u_int namelen, void *oldp, size_t *oldlenp,
}
/*
- * Skew the timehands according to any adjfreq(2)/adjtime(2) adjustments.
+ * Skew the timehands according to any adjtime(2) adjustment.
*/
void
ntp_update_second(struct timehands *th)
@@ -766,7 +768,6 @@ ntp_update_second(struct timehands *th)
adj = MAX(-5000, th->th_adjtimedelta);
th->th_adjtimedelta -= adj;
th->th_adjustment = (adj * 1000) << 32;
- th->th_adjustment += th->th_counter->tc_freq_adj;
}
void