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
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
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.6 2004/09/05 02:09:24 dillon Exp $
40 #include <sys/types.h>
41 #include <sys/times.h>
43 #include <sys/syssgi.h>
46 static void adjclock(struct timeval *);
49 * sends to the slaves the corrections for their clocks after fixing our
57 struct timeval adjlocal;
61 mstotvround(&adjlocal, avdelta);
63 for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) {
64 if (htp->delta != HOSTDOWN) {
65 corr = avdelta - htp->delta;
66 /* If the other machine is off in the weeds, set its time directly.
67 * If a slave gets the wrong day, the original code would simply
68 * fix the minutes. If you fix a network partition, you can get
69 * into such situations.
72 || corr >= MAXADJ*1000
73 || corr <= -MAXADJ*1000) {
75 (void)gettimeofday(&to.tsp_time,0);
76 timevaladd(&to.tsp_time, &adjlocal);
77 to.tsp_type = TSP_SETTIME;
79 mstotvround(&to.tsp_time, corr);
80 to.tsp_type = TSP_ADJTIME;
82 strlcpy(to.tsp_name, hostname, sizeof(to.tsp_name));
83 answer = acksend(&to, &htp->addr, htp->name,
86 htp->delta = HOSTDOWN;
88 "no reply to time correction from %s",
90 if (++htp->noanswer >= LOSTHOST) {
93 "purging %s for not answering\n",
104 * adjust our own clock now that we are not sending it out
111 adjclock(struct timeval *corr)
113 static int passes = 0;
114 static int smoother = 0;
115 long delta; /* adjustment in usec */
120 if (!timerisset(corr))
124 if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) {
125 delta = adj.tv_sec*1000000 + adj.tv_usec;
126 /* If the correction is less than the minimum round
127 * trip time for an ICMP packet, and thus
128 * less than the likely error in the measurement,
129 * do not do the entire correction. Do half
130 * or a quarter of it.
133 if (delta > -MIN_ROUND*1000
134 && delta < MIN_ROUND*1000) {
137 ndelta = delta >> smoother;
140 "trimming delta %ld usec to %ld\n",
142 adj.tv_usec = ndelta;
144 } else if (smoother > 0) {
147 if (0 > adjtime(corr, 0)) {
148 syslog(LOG_ERR, "adjtime: %m");
151 && (delta < -BIG_ADJ || delta > BIG_ADJ)) {
155 "large time adjustment of %+.3f sec",
160 "clock correction %ld sec too large to adjust",
162 (void) gettimeofday(&now, 0);
163 timevaladd(&now, corr);
164 if (settimeofday(&now, 0) < 0)
165 syslog(LOG_ERR, "settimeofday: %m");
169 /* Accumulate the total change, and use it to adjust the basic
173 #define F_USEC_PER_SEC (1000000*1.0) /* reduce typos */
174 #define F_NSEC_PER_SEC (F_USEC_PER_SEC*1000.0)
176 extern char *timetrim_fn;
177 extern char *timetrim_wpat;
178 extern long timetrim;
179 extern double tot_adj, hr_adj; /* totals in nsec */
180 extern double tot_ticks, hr_ticks;
182 static double nag_tick;
183 double cur_ticks, hr_delta_ticks, tot_delta_ticks;
184 double tru_tot_adj, tru_hr_adj; /* nsecs of adjustment */
185 double tot_trim, hr_trim; /* nsec/sec */
189 cur_ticks = times(&tm);
190 tot_adj += delta*1000.0;
191 hr_adj += delta*1000.0;
193 tot_delta_ticks = cur_ticks-tot_ticks;
194 if (tot_delta_ticks >= 16*SECDAY*CLK_TCK) {
195 tot_adj -= rint(tot_adj/16);
196 tot_ticks += rint(tot_delta_ticks/16);
197 tot_delta_ticks = cur_ticks-tot_ticks;
199 hr_delta_ticks = cur_ticks-hr_ticks;
201 tru_hr_adj = hr_adj + timetrim*rint(hr_delta_ticks/CLK_TCK);
202 tru_tot_adj = (tot_adj
203 + timetrim*rint(tot_delta_ticks/CLK_TCK));
205 if (hr_delta_ticks >= SECDAY*CLK_TCK
206 || (tot_delta_ticks < 4*SECDAY*CLK_TCK
207 && hr_delta_ticks >= SECHR*CLK_TCK)
208 || (trace && hr_delta_ticks >= (SECHR/10)*CLK_TCK)) {
210 tot_trim = rint(tru_tot_adj*CLK_TCK/tot_delta_ticks);
211 hr_trim = rint(tru_hr_adj*CLK_TCK/hr_delta_ticks);
214 || (abs(timetrim - hr_trim) > 100000.0
216 && ((cur_ticks - nag_tick)
217 >= 24*SECDAY*CLK_TCK))) {
218 nag_tick = cur_ticks;
220 "%+.3f/%.2f or %+.3f/%.2f sec/hr; timetrim=%+.0f or %+.0f",
221 tru_tot_adj/F_NSEC_PER_SEC,
222 tot_delta_ticks/(SECHR*CLK_TCK*1.0),
223 tru_hr_adj/F_NSEC_PER_SEC,
224 hr_delta_ticks/(SECHR*CLK_TCK*1.0),
229 if (tot_trim < -MAX_TRIM || tot_trim > MAX_TRIM) {
230 tot_ticks = hr_ticks;
232 } else if (0 > syssgi(SGI_SETTIMETRIM,
234 syslog(LOG_ERR, "SETTIMETRIM(%d): %m",
237 if (0 != timetrim_fn) {
238 timetrim_st = fopen(timetrim_fn, "w");
239 if (0 == timetrim_st) {
240 syslog(LOG_ERR, "fopen(%s): %m",
243 if (0 > fprintf(timetrim_st,
252 (void)fclose(timetrim_st);
256 tot_adj -= ((tot_trim - timetrim)
257 * rint(tot_delta_ticks/CLK_TCK));
261 hr_ticks = cur_ticks;
269 /* adjust the time in a message by the time it
273 adj_msg_time(struct tsp *msg, struct timeval *now)
275 msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec);
276 msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec);
278 while (msg->tsp_time.tv_usec < 0) {
279 msg->tsp_time.tv_sec--;
280 msg->tsp_time.tv_usec += 1000000;
282 while (msg->tsp_time.tv_usec >= 1000000) {
283 msg->tsp_time.tv_sec++;
284 msg->tsp_time.tv_usec -= 1000000;