]>
git.saurik.com Git - apple/network_cmds.git/blob - timed.tproj/timed.tproj/correct.c
be9867705d858280b82cb5b2f9dd60b569547c9f
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1985, 1993
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 static char sccsid
[] = "@(#)correct.c 8.1 (Berkeley) 6/6/93";
62 #ident "$Revision: 1.1 $"
67 #include <sys/types.h>
68 #include <sys/times.h>
70 #include <sys/syssgi.h>
73 static void adjclock
__P((struct timeval
*));
76 * sends to the slaves the corrections for their clocks after fixing our
85 struct timeval adjlocal
;
89 mstotvround(&adjlocal
, avdelta
);
91 for (htp
= self
.l_fwd
; htp
!= &self
; htp
= htp
->l_fwd
) {
92 if (htp
->delta
!= HOSTDOWN
) {
93 corr
= avdelta
- htp
->delta
;
94 /* If the other machine is off in the weeds, set its time directly.
95 * If a slave gets the wrong day, the original code would simply
96 * fix the minutes. If you fix a network partition, you can get
97 * into such situations.
100 || corr
>= MAXADJ
*1000
101 || corr
<= -MAXADJ
*1000) {
103 (void)gettimeofday(&to
.tsp_time
,0);
104 timevaladd(&to
.tsp_time
, &adjlocal
);
105 to
.tsp_type
= TSP_SETTIME
;
107 mstotvround(&to
.tsp_time
, corr
);
108 to
.tsp_type
= TSP_ADJTIME
;
110 (void)strcpy(to
.tsp_name
, hostname
);
111 answer
= acksend(&to
, &htp
->addr
, htp
->name
,
114 htp
->delta
= HOSTDOWN
;
116 "no reply to time correction from %s",
118 if (++htp
->noanswer
>= LOSTHOST
) {
121 "purging %s for not answering\n",
132 * adjust our own clock now that we are not sending it out
140 struct timeval
*corr
;
142 static int passes
= 0;
143 static int smoother
= 0;
144 long delta
; /* adjustment in usec */
149 if (!timerisset(corr
))
153 if (adj
.tv_sec
< MAXADJ
&& adj
.tv_sec
> - MAXADJ
) {
154 delta
= adj
.tv_sec
*1000000 + adj
.tv_usec
;
155 /* If the correction is less than the minimum round
156 * trip time for an ICMP packet, and thus
157 * less than the likely error in the measurement,
158 * do not do the entire correction. Do half
159 * or a quarter of it.
162 if (delta
> -MIN_ROUND
*1000
163 && delta
< MIN_ROUND
*1000) {
166 ndelta
= delta
>> smoother
;
169 "trimming delta %ld usec to %ld\n",
171 adj
.tv_usec
= ndelta
;
173 } else if (smoother
> 0) {
176 if (0 > adjtime(corr
, 0)) {
177 syslog(LOG_ERR
, "adjtime: %m");
180 && (delta
< -BIG_ADJ
|| delta
> BIG_ADJ
)) {
184 "large time adjustment of %+.3f sec",
189 "clock correction %d sec too large to adjust",
191 (void) gettimeofday(&now
, 0);
192 timevaladd(&now
, corr
);
193 if (settimeofday(&now
, 0) < 0)
194 syslog(LOG_ERR
, "settimeofday: %m");
198 /* Accumulate the total change, and use it to adjust the basic
202 #define F_USEC_PER_SEC (1000000*1.0) /* reduce typos */
203 #define F_NSEC_PER_SEC (F_USEC_PER_SEC*1000.0)
205 extern char *timetrim_fn
;
206 extern char *timetrim_wpat
;
207 extern long timetrim
;
208 extern double tot_adj
, hr_adj
; /* totals in nsec */
209 extern double tot_ticks
, hr_ticks
;
211 static double nag_tick
;
212 double cur_ticks
, hr_delta_ticks
, tot_delta_ticks
;
213 double tru_tot_adj
, tru_hr_adj
; /* nsecs of adjustment */
214 double tot_trim
, hr_trim
; /* nsec/sec */
218 cur_ticks
= times(&tm
);
219 tot_adj
+= delta
*1000.0;
220 hr_adj
+= delta
*1000.0;
222 tot_delta_ticks
= cur_ticks
-tot_ticks
;
223 if (tot_delta_ticks
>= 16*SECDAY
*CLK_TCK
) {
224 tot_adj
-= rint(tot_adj
/16);
225 tot_ticks
+= rint(tot_delta_ticks
/16);
226 tot_delta_ticks
= cur_ticks
-tot_ticks
;
228 hr_delta_ticks
= cur_ticks
-hr_ticks
;
230 tru_hr_adj
= hr_adj
+ timetrim
*rint(hr_delta_ticks
/CLK_TCK
);
231 tru_tot_adj
= (tot_adj
232 + timetrim
*rint(tot_delta_ticks
/CLK_TCK
));
234 if (hr_delta_ticks
>= SECDAY
*CLK_TCK
235 || (tot_delta_ticks
< 4*SECDAY
*CLK_TCK
236 && hr_delta_ticks
>= SECHR
*CLK_TCK
)
237 || (trace
&& hr_delta_ticks
>= (SECHR
/10)*CLK_TCK
)) {
239 tot_trim
= rint(tru_tot_adj
*CLK_TCK
/tot_delta_ticks
);
240 hr_trim
= rint(tru_hr_adj
*CLK_TCK
/hr_delta_ticks
);
243 || (abs(timetrim
- hr_trim
) > 100000.0
245 && ((cur_ticks
- nag_tick
)
246 >= 24*SECDAY
*CLK_TCK
))) {
247 nag_tick
= cur_ticks
;
249 "%+.3f/%.2f or %+.3f/%.2f sec/hr; timetrim=%+.0f or %+.0f",
250 tru_tot_adj
/F_NSEC_PER_SEC
,
251 tot_delta_ticks
/(SECHR
*CLK_TCK
*1.0),
252 tru_hr_adj
/F_NSEC_PER_SEC
,
253 hr_delta_ticks
/(SECHR
*CLK_TCK
*1.0),
258 if (tot_trim
< -MAX_TRIM
|| tot_trim
> MAX_TRIM
) {
259 tot_ticks
= hr_ticks
;
261 } else if (0 > syssgi(SGI_SETTIMETRIM
,
263 syslog(LOG_ERR
, "SETTIMETRIM(%d): %m",
266 if (0 != timetrim_fn
) {
267 timetrim_st
= fopen(timetrim_fn
, "w");
268 if (0 == timetrim_st
) {
269 syslog(LOG_ERR
, "fopen(%s): %m",
272 if (0 > fprintf(timetrim_st
,
281 (void)fclose(timetrim_st
);
285 tot_adj
-= ((tot_trim
- timetrim
)
286 * rint(tot_delta_ticks
/CLK_TCK
));
290 hr_ticks
= cur_ticks
;
298 /* adjust the time in a message by the time it
302 adj_msg_time(msg
, now
)
306 msg
->tsp_time
.tv_sec
+= (now
->tv_sec
- from_when
.tv_sec
);
307 msg
->tsp_time
.tv_usec
+= (now
->tv_usec
- from_when
.tv_usec
);
309 while (msg
->tsp_time
.tv_usec
< 0) {
310 msg
->tsp_time
.tv_sec
--;
311 msg
->tsp_time
.tv_usec
+= 1000000;
313 while (msg
->tsp_time
.tv_usec
>= 1000000) {
314 msg
->tsp_time
.tv_sec
++;
315 msg
->tsp_time
.tv_usec
-= 1000000;