153 lines
3.9 KiB
C
153 lines
3.9 KiB
C
|
#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 */
|