]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/libntp/adjtime.c
This commit was generated by cvs2svn to compensate for changes in r56067,
[FreeBSD/FreeBSD.git] / contrib / ntp / libntp / adjtime.c
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 */