xref: /freebsd/contrib/ntp/libntp/adjtime.c (revision 817420dc8eac7df799c78f5309b75092b7f7cd40)
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #ifdef NEED_HPUX_ADJTIME
6 /*************************************************************************/
7 /* (c) Copyright Tai Jin, 1988.  All Rights Reserved.                    */
8 /*     Hewlett-Packard Laboratories.                                     */
9 /*                                                                       */
10 /* Permission is hereby granted for unlimited modification, use, and     */
11 /* distribution.  This software is made available with no warranty of    */
12 /* any kind, express or implied.  This copyright notice must remain      */
13 /* intact in all versions of this software.                              */
14 /*                                                                       */
15 /* The author would appreciate it if any bug fixes and enhancements were */
16 /* to be sent back to him for incorporation into future versions of this */
17 /* software.  Please send changes to tai@iag.hp.com or ken@sdd.hp.com.   */
18 /*************************************************************************/
19 
20 /*
21  * Revision history
22  *
23  * 9 Jul 94	David L. Mills, Unibergity of Delabunch
24  *		Implemented variable threshold to limit age of
25  *		corrections; reformatted code for readability.
26  */
27 
28 #ifndef lint
29 static char RCSid[] = "adjtime.c,v 3.1 1993/07/06 01:04:42 jbj Exp";
30 #endif
31 
32 #include <sys/types.h>
33 #include <sys/ipc.h>
34 #include <sys/msg.h>
35 #include <time.h>
36 #include <signal.h>
37 #include "adjtime.h"
38 
39 #define abs(x)  ((x) < 0 ? -(x) : (x))
40 
41 /*
42  * The following paramters are appropriate for an NTP adjustment
43  * interval of one second.
44  */
45 #define ADJ_THRESH 200		/* initial threshold */
46 #define ADJ_DELTA 4		/* threshold decrement */
47 
48 static long adjthresh;		/* adjustment threshold */
49 static long saveup;		/* corrections accumulator */
50 
51 /*
52  * clear_adjtime - reset accumulator and threshold variables
53  */
54 void
55 _clear_adjtime(void)
56 {
57 	saveup = 0;
58 	adjthresh = ADJ_THRESH;
59 }
60 
61 /*
62  * adjtime - hp-ux copout of the standard Unix adjtime() system call
63  */
64 int
65 adjtime(
66 	register struct timeval *delta,
67 	register struct timeval *olddelta
68 	)
69 {
70 	struct timeval newdelta;
71 
72 	/*
73 	 * Corrections greater than one second are done immediately.
74 	 */
75 	if (delta->tv_sec) {
76 		adjthresh = ADJ_THRESH;
77 		saveup = 0;
78 		return(_adjtime(delta, olddelta));
79 	}
80 
81 	/*
82 	 * Corrections less than one second are accumulated until
83 	 * tripping a threshold, which is initially set at ADJ_THESH and
84 	 * reduced in ADJ_DELTA steps to zero. The idea here is to
85 	 * introduce large corrections quickly, while making sure that
86 	 * small corrections are introduced without excessive delay. The
87 	 * idea comes from the ARPAnet routing update algorithm.
88 	 */
89 	saveup += delta->tv_usec;
90 	if (abs(saveup) >= adjthresh) {
91 		adjthresh = ADJ_THRESH;
92 		newdelta.tv_sec = 0;
93 		newdelta.tv_usec = saveup;
94 		saveup = 0;
95 		return(_adjtime(&newdelta, olddelta));
96 	} else {
97 		adjthresh -= ADJ_DELTA;
98 	}
99 
100 	/*
101 	 * While nobody uses it, return the residual before correction,
102 	 * as per Unix convention.
103 	 */
104 	if (olddelta)
105 	    olddelta->tv_sec = olddelta->tv_usec = 0;
106 	return(0);
107 }
108 
109 /*
110  * _adjtime - does the actual work
111  */
112 int
113 _adjtime(
114 	register struct timeval *delta,
115 	register struct timeval *olddelta
116 	)
117 {
118 	register int mqid;
119 	MsgBuf msg;
120 	register MsgBuf *msgp = &msg;
121 
122 	/*
123 	 * Get the key to the adjtime message queue (note that we must
124 	 * get it every time because the queue might have been removed
125 	 * and recreated)
126 	 */
127 	if ((mqid = msgget(KEY, 0)) == -1)
128 	    return (-1);
129 	msgp->msgb.mtype = CLIENT;
130 	msgp->msgb.tv = *delta;
131 	if (olddelta)
132 	    msgp->msgb.code = DELTA2;
133 	else
134 	    msgp->msgb.code = DELTA1;
135 
136 	/*
137 	 * Tickle adjtimed and snatch residual, if indicated. Lots of
138 	 * fanatic error checking here.
139 	 */
140 	if (msgsnd(mqid, &msgp->msgp, MSGSIZE, 0) == -1)
141 	    return (-1);
142 	if (olddelta) {
143 		if (msgrcv(mqid, &msgp->msgp, MSGSIZE, SERVER, 0) == -1)
144 		    return (-1);
145 		*olddelta = msgp->msgb.tv;
146 	}
147 	return (0);
148 }
149 
150 #else /* not NEED_HPUX_ADJTIME */
151 int adjtime_bs;
152 #endif /* not NEED_HPUX_ADJTIME */
153