Merge commit 'crater/master'
[dragonfly.git] / usr.sbin / timed / timed / correct.c
blob7ebdc59c242fc590a2d85b4d33508c2d749b973b
1 /*-
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
33 * @(#)correct.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: src/usr.sbin/timed/timed/correct.c,v 1.4 1999/08/28 01:20:17 peter Exp $
35 * $DragonFly: src/usr.sbin/timed/timed/correct.c,v 1.8 2004/09/05 02:20:15 dillon Exp $
38 #include "globals.h"
39 #include <math.h>
40 #include <sys/types.h>
41 #include <sys/times.h>
43 static void adjclock(struct timeval *);
46 * sends to the slaves the corrections for their clocks after fixing our
47 * own
49 void
50 correct(long avdelta)
52 struct hosttbl *htp;
53 int corr;
54 struct timeval adjlocal;
55 struct tsp to;
56 struct tsp *answer;
58 mstotvround(&adjlocal, avdelta);
60 for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
61 if (htp->delta != HOSTDOWN) {
62 corr = avdelta - htp->delta;
63 /* If the other machine is off in the weeds, set its time directly.
64 * If a slave gets the wrong day, the original code would simply
65 * fix the minutes. If you fix a network partition, you can get
66 * into such situations.
68 if (htp->need_set
69 || corr >= MAXADJ*1000
70 || corr <= -MAXADJ*1000) {
71 htp->need_set = 0;
72 gettimeofday(&to.tsp_time,0);
73 timevaladd(&to.tsp_time, &adjlocal);
74 to.tsp_type = TSP_SETTIME;
75 } else {
76 mstotvround(&to.tsp_time, corr);
77 to.tsp_type = TSP_ADJTIME;
79 strlcpy(to.tsp_name, hostname, sizeof(to.tsp_name));
80 answer = acksend(&to, &htp->addr, htp->name,
81 TSP_ACK, 0, 0);
82 if (!answer) {
83 htp->delta = HOSTDOWN;
84 syslog(LOG_WARNING,
85 "no reply to time correction from %s",
86 htp->name);
87 if (++htp->noanswer >= LOSTHOST) {
88 if (trace) {
89 fprintf(fd,
90 "purging %s for not answering\n",
91 htp->name);
92 fflush(fd);
94 htp = remmach(htp);
101 * adjust our own clock now that we are not sending it out
103 adjclock(&adjlocal);
107 static void
108 adjclock(struct timeval *corr)
110 static int passes = 0;
111 static int smoother = 0;
112 long delta; /* adjustment in usec */
113 long ndelta;
114 struct timeval now;
115 struct timeval adj;
117 if (!timerisset(corr))
118 return;
120 adj = *corr;
121 if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
122 delta = adj.tv_sec*1000000 + adj.tv_usec;
123 /* If the correction is less than the minimum round
124 * trip time for an ICMP packet, and thus
125 * less than the likely error in the measurement,
126 * do not do the entire correction. Do half
127 * or a quarter of it.
130 if (delta > -MIN_ROUND*1000
131 && delta < MIN_ROUND*1000) {
132 if (smoother <= 4)
133 smoother++;
134 ndelta = delta >> smoother;
135 if (trace)
136 fprintf(fd,
137 "trimming delta %ld usec to %ld\n",
138 delta, ndelta);
139 adj.tv_usec = ndelta;
140 adj.tv_sec = 0;
141 } else if (smoother > 0) {
142 smoother--;
144 if (0 > adjtime(corr, 0)) {
145 syslog(LOG_ERR, "adjtime: %m");
147 if (passes > 1
148 && (delta < -BIG_ADJ || delta > BIG_ADJ)) {
149 smoother = 0;
150 passes = 0;
151 syslog(LOG_WARNING,
152 "large time adjustment of %+.3f sec",
153 delta/1000000.0);
155 } else {
156 syslog(LOG_WARNING,
157 "clock correction %ld sec too large to adjust",
158 adj.tv_sec);
159 gettimeofday(&now, 0);
160 timevaladd(&now, corr);
161 if (settimeofday(&now, 0) < 0)
162 syslog(LOG_ERR, "settimeofday: %m");
167 /* adjust the time in a message by the time it
168 * spent in the queue
170 void
171 adj_msg_time(struct tsp *msg, struct timeval *now)
173 msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
174 msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
176 while (msg->tsp_time.tv_usec < 0) {
177 msg->tsp_time.tv_sec--;
178 msg->tsp_time.tv_usec += 1000000;
180 while (msg->tsp_time.tv_usec >= 1000000) {
181 msg->tsp_time.tv_sec++;
182 msg->tsp_time.tv_usec -= 1000000;