summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/libntp/adjtime.c
blob: 72be86090b47dcb50693e9f5da9c0fb052b5329e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef NEED_HPUX_ADJTIME
/*************************************************************************/
/* (c) Copyright Tai Jin, 1988.  All Rights Reserved.                    */
/*     Hewlett-Packard Laboratories.                                     */
/*                                                                       */
/* Permission is hereby granted for unlimited modification, use, and     */
/* distribution.  This software is made available with no warranty of    */
/* any kind, express or implied.  This copyright notice must remain      */
/* intact in all versions of this software.                              */
/*                                                                       */
/* The author would appreciate it if any bug fixes and enhancements were */
/* to be sent back to him for incorporation into future versions of this */
/* software.  Please send changes to tai@iag.hp.com or ken@sdd.hp.com.   */
/*************************************************************************/

/*
 * Revision history
 *
 * 9 Jul 94	David L. Mills, Unibergity of Delabunch
 *		Implemented variable threshold to limit age of
 *		corrections; reformatted code for readability.
 */

#ifndef lint
static char RCSid[] = "adjtime.c,v 3.1 1993/07/06 01:04:42 jbj Exp";
#endif

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <time.h>
#include <signal.h>
#include "adjtime.h"

#define abs(x)  ((x) < 0 ? -(x) : (x))

/*
 * The following paramters are appropriate for an NTP adjustment
 * interval of one second.
 */
#define ADJ_THRESH 200		/* initial threshold */
#define ADJ_DELTA 4		/* threshold decrement */

static long adjthresh;		/* adjustment threshold */
static long saveup;		/* corrections accumulator */

/*
 * clear_adjtime - reset accumulator and threshold variables
 */
void
_clear_adjtime(void)
{
	saveup = 0;
	adjthresh = ADJ_THRESH;
}

/*
 * adjtime - hp-ux copout of the standard Unix adjtime() system call
 */
int
adjtime(
	register struct timeval *delta,
	register struct timeval *olddelta
	)
{
	struct timeval newdelta;

	/*
	 * Corrections greater than one second are done immediately.
	 */
	if (delta->tv_sec) {
		adjthresh = ADJ_THRESH;
		saveup = 0;
		return(_adjtime(delta, olddelta));
	}

	/*
	 * Corrections less than one second are accumulated until
	 * tripping a threshold, which is initially set at ADJ_THESH and
	 * reduced in ADJ_DELTA steps to zero. The idea here is to
	 * introduce large corrections quickly, while making sure that
	 * small corrections are introduced without excessive delay. The
	 * idea comes from the ARPAnet routing update algorithm.
	 */
	saveup += delta->tv_usec;
	if (abs(saveup) >= adjthresh) {
		adjthresh = ADJ_THRESH;
		newdelta.tv_sec = 0;
		newdelta.tv_usec = saveup;
		saveup = 0;
		return(_adjtime(&newdelta, olddelta));
	} else {
		adjthresh -= ADJ_DELTA;
	}

	/*
	 * While nobody uses it, return the residual before correction,
	 * as per Unix convention.
	 */
	if (olddelta)
	    olddelta->tv_sec = olddelta->tv_usec = 0;
	return(0);
}

/*
 * _adjtime - does the actual work
 */
int
_adjtime(
	register struct timeval *delta,
	register struct timeval *olddelta
	)
{
	register int mqid;
	MsgBuf msg;
	register MsgBuf *msgp = &msg;

	/*
	 * Get the key to the adjtime message queue (note that we must
	 * get it every time because the queue might have been removed
	 * and recreated)
	 */
	if ((mqid = msgget(KEY, 0)) == -1)
	    return (-1);
	msgp->msgb.mtype = CLIENT;
	msgp->msgb.tv = *delta;
	if (olddelta)
	    msgp->msgb.code = DELTA2;
	else
	    msgp->msgb.code = DELTA1;

	/*
	 * Tickle adjtimed and snatch residual, if indicated. Lots of
	 * fanatic error checking here.
	 */
	if (msgsnd(mqid, &msgp->msgp, MSGSIZE, 0) == -1)
	    return (-1);
	if (olddelta) {
		if (msgrcv(mqid, &msgp->msgp, MSGSIZE, SERVER, 0) == -1)
		    return (-1);
		*olddelta = msgp->msgb.tv;
	}
	return (0);
}

#else /* not NEED_HPUX_ADJTIME */
int adjtime_bs;
#endif /* not NEED_HPUX_ADJTIME */
OpenPOWER on IntegriCloud