1: #if !defined(lint) && defined(DOSCCS)
2: static char *RCSid = "$Source: /usr/src/new/ntp/ntp_adjust.c,v $ $Revision: 3.4.1.5 $ $Date: 95/01/27 17:23:36 $";
3: #endif
4:
5: /*
6: * This module implemenets the logical Local Clock, as described in section
7: * 5. of the NTP specification.
8: *
9: * $Log: ntp_adjust.c,v $
10: * Revision 3.4.1.5 95/01/27 17:23:36 sms
11: * Remove SETTICKADJ - see rational in ntpd.c
12: *
13: * Revision 3.4.1.4 89/05/18 18:23:36 louie
14: * A couple of changes to debug NeXT support in ntp_adjust.c
15: *
16: * Revision 3.4.1.3 89/04/07 18:05:17 louie
17: * Removed unused variable from ntp_adjust.c module.
18: *
19: * Revision 3.4.1.2 89/03/22 18:30:52 louie
20: * patch3: Use new RCS headers.
21: *
22: * Revision 3.4.1.1 89/03/20 00:09:06 louie
23: * patch1: Don't zero the drift compensation or compliance values when a step
24: * patch1: adjustment of the clock occurs. Use symbolic definition of
25: * patch1: CLOCK_FACTOR rather than constant.
26: *
27: * Revision 3.4 89/03/17 18:37:03 louie
28: * Latest test release.
29: *
30: * Revision 3.3.1.2 89/03/17 18:25:03 louie
31: * Applied suggested code from Dennis Ferguson for logical clock model based on
32: * the equations in section 5. Many thanks.
33: *
34: * Revision 3.3.1.1 89/03/16 19:19:29 louie
35: * Attempt to implement using the equations in section 5 of the NTP spec,
36: * rather then modeling the Fuzzball implementation.
37: *
38: * Revision 3.3 89/03/15 14:19:45 louie
39: * New baseline for next release.
40: *
41: * Revision 3.2.1.1 89/03/15 13:47:24 louie
42: * Use "%f" in format strings rather than "%lf".
43: *
44: * Revision 3.2 89/03/07 18:22:54 louie
45: * New version of UNIX NTP daemon and software based on the 6 March 1989
46: * draft of the new NTP protocol specification. This module attempts to
47: * conform to the new logical clock described in section 5 of the spec. Note
48: * that the units of the drift_compensation register have changed.
49: *
50: * This version also accumulates the residual adjtime() truncation and
51: * adds it in on subsequent adjustments.
52: *
53: * Revision 3.1.1.1 89/02/15 08:55:48 louie
54: * *** empty log message ***
55: *
56: *
57: * Revision 3.1 89/01/30 14:43:08 louie
58: * Second UNIX NTP test release.
59: *
60: * Revision 3.0 88/12/12 16:00:38 louie
61: * Test release of new UNIX NTP software. This version should conform to the
62: * revised NTP protocol specification.
63: *
64: */
65:
66: #include <stdio.h>
67: #include <sys/types.h>
68: #include <sys/param.h>
69: #include <sys/socket.h>
70: #include <sys/time.h>
71: #include <sys/ioctl.h>
72: #include <sys/resource.h>
73:
74: #include <netinet/in.h>
75: #include <netinet/in_systm.h>
76: #include <netinet/ip.h>
77: #include <netinet/udp.h>
78:
79: #include <arpa/inet.h>
80: #include <netdb.h>
81: #include <strings.h>
82: #include <errno.h>
83: #include <syslog.h>
84:
85: #include "ntp.h"
86:
87: #ifdef DEBUG
88: extern int debug;
89: #endif
90:
91: extern int doset;
92: extern int debuglevel;
93: extern char *ntoa();
94: extern struct sysdata sys;
95:
96: double drift_comp = 0.0,
97: compliance,
98: clock_adjust;
99: long update_timer = 0;
100:
101: int adj_precision;
102: double adj_residual;
103: int firstpass = 1;
104:
105: #define abs(x) ((x) < 0 ? -(x) : (x))
106:
107: void
108: init_logical_clock()
109: {
110: adj_precision = 1;
111: /*
112: * If you have the "fix" for adjtime() installed in you kernel, you'll
113: * have to make sure that adj_precision is set to 1 here.
114: */
115: }
116:
117:
118: /*
119: * 5.0 Logical clock procedure
120: *
121: * Only paramter is an offset to vary the clock by, in seconds. We'll either
122: * arrange for the clock to slew to accomodate the adjustment, or just preform
123: * a step adjustment if the offset is too large.
124: *
125: * The update which is to be performed is left in the external
126: * clock_adjust.
127: *
128: * Returns non-zero if clock was reset rather than slewed.
129: *
130: * Many thanks for Dennis Ferguson <dennis@gw.ccie.utoronto.ca> for his
131: * corrections to my code.
132: */
133:
134: int
135: adj_logical(offset)
136: double offset;
137: {
138: struct timeval tv1, tv2;
139: #ifdef XADJTIME2
140: struct timeval delta, olddelta;
141: #endif
142:
143: /*
144: * Now adjust the logical clock
145: */
146: if (!doset)
147: return 0;
148:
149: adj_residual = 0.0;
150: if (offset > CLOCK_MAX || offset < -CLOCK_MAX) {
151: double steptime = offset;
152:
153: (void) gettimeofday(&tv2, (struct timezone *) 0);
154: steptime += tv2.tv_sec;
155: steptime += tv2.tv_usec / 1000000.0;
156: tv1.tv_sec = steptime;
157: tv1.tv_usec = (steptime - tv1.tv_sec) * 1000000;
158: #ifdef DEBUG
159: if (debug > 2) {
160: steptime = (tv1.tv_sec + tv1.tv_usec/1000000.0) -
161: (tv2.tv_sec + tv2.tv_usec/1000000.0);
162: printf("adj_logical: %f %f\n", offset, steptime);
163: }
164: #endif
165: if (settimeofday(&tv1, (struct timezone *) 0) < 0) {
166: syslog(LOG_ERR, "Can't set time: %m");
167: return(-1);
168: }
169: clock_adjust = 0.0;
170: firstpass = 1;
171: update_timer = 0;
172: return (1); /* indicate that step adjustment was done */
173: } else {
174: double ai;
175:
176: /*
177: * If this is our very first adjustment, don't touch
178: * the drift compensation (this is f in the spec
179: * equations), else update using the *old* value
180: * of the compliance.
181: */
182: clock_adjust = offset;
183: if (firstpass)
184: firstpass = 0;
185: else if (update_timer > 0) {
186: ai = abs(compliance);
187: ai = (double)(1<<CLOCK_COMP) -
188: (double)(1<<CLOCK_FACTOR) * ai;
189: if (ai < 1.0) /* max(... , 1.0) */
190: ai = 1.0;
191: drift_comp += offset / (ai * (double)update_timer);
192: }
193:
194: /*
195: * Set the timer to zero. adj_host_clock() increments it
196: * so we can tell the period between updates.
197: */
198: update_timer = 0;
199:
200: /*
201: * Now update the compliance. The compliance is h in the
202: * equations.
203: */
204: compliance += (offset - compliance)/(double)(1<<CLOCK_TRACK);
205:
206: #ifdef XADJTIME2
207: delta.tv_sec = offset;
208: delta.tv_usec = (offset - delta.tv_sec) * 1000;
209: (void) adjtime2(&delta, &olddelta);
210: #endif
211: return(0);
212: }
213: }
214:
215: #ifndef XADJTIME2
216: extern int adjtime();
217:
218: /*
219: * This is that routine that performs the periodic clock adjustment.
220: * The procedure is best described in the the NTP document. In a
221: * nutshell, we prefer to do lots of small evenly spaced adjustments.
222: * The alternative, one large adjustment, creates two much of a
223: * clock disruption and as a result oscillation.
224: *
225: * This function is called every 2**CLOCK_ADJ seconds.
226: *
227: */
228:
229: /*
230: * global for debugging?
231: */
232: double adjustment;
233:
234: void
235: adj_host_clock()
236: {
237:
238: struct timeval delta, olddelta;
239:
240: if (!doset)
241: return;
242:
243: /*
244: * Add update period into timer so we know how long it
245: * took between the last update and the next one.
246: */
247: update_timer += 1<<CLOCK_ADJ;
248: /*
249: * Should check to see if update_timer > 1 day here?
250: */
251:
252: /*
253: * Compute phase part of adjustment here and update clock_adjust.
254: * Note that the equations used here are implicit in the last
255: * two equations in the spec (in particular, look at the equation
256: * for g and figure out how to find the k==1 term given the k==0 term.)
257: */
258: adjustment = clock_adjust / (double)(1<<CLOCK_PHASE);
259: clock_adjust -= adjustment;
260:
261: /*
262: * Now add in the frequency component. Be careful to note that
263: * the ni occurs in the last equation since those equations take
264: * you from 64 second update to 64 second update (ei is the total
265: * adjustment done over 64 seconds) and we're only deal in the
266: * little 4 second adjustment interval here.
267: */
268: adjustment += drift_comp / (double)(1<<CLOCK_FREQ);
269:
270: /*
271: * Add in old adjustment residual
272: */
273: adjustment += adj_residual;
274:
275: /*
276: * Simplify. Adjustment shouldn't be bigger than 2 ms. Hope
277: * writer of spec was truth telling.
278: */
279: #ifdef DEBUG
280: delta.tv_sec = adjustment;
281: if (debug && delta.tv_sec) abort();
282: #else
283: delta.tv_sec = 0;
284: #endif
285: delta.tv_usec = ((long)(adjustment * 1000000.0) / adj_precision)
286: * adj_precision;
287:
288: adj_residual = adjustment - (double) delta.tv_usec / 1000000.0;
289:
290: if (delta.tv_usec == 0)
291: return;
292:
293: if (adjtime(&delta, &olddelta) < 0)
294: syslog(LOG_ERR, "Can't adjust time: %m");
295:
296: #ifdef DEBUG
297: if(debug > 2)
298: printf("adj: %ld us %f %f\n",
299: delta.tv_usec, drift_comp, clock_adjust);
300: #endif
301: }
302: #endif
Defined functions
Defined variables
RCSid
defined in line
2;
never used
Defined macros
abs
defined in line
105; used 1 times