ntp_adjust.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 335 行

C
335
字号
#ifndef lintstatic	char	*sccsid = "@(#)ntp_adjust.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989-1990 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/#ifndef lintstatic char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntp_adjust.c,v $ $Revision: 3.4.1.4 $ $Date: 89/05/18 18:23:36 $";#endif/* * This module implemenets the logical Local Clock, as described in section * 5. of the NTP specification. * * $Log:	ntp_adjust.c,v $ * Revision 3.4.1.4  89/05/18  18:23:36  louie * A couple of changes to debug NeXT support in ntp_adjust.c *  * Revision 3.4.1.3  89/04/07  18:05:17  louie * Removed unused variable from ntp_adjust.c module. *  * Revision 3.4.1.2  89/03/22  18:30:52  louie * patch3: Use new RCS headers. *  * Revision 3.4.1.1  89/03/20  00:09:06  louie * patch1: Don't zero the drift compensation or compliance values when a step * patch1: adjustment of the clock occurs.  Use symbolic definition of * patch1: CLOCK_FACTOR rather than constant. *  * Revision 3.4  89/03/17  18:37:03  louie * Latest test release. *  * Revision 3.3.1.2  89/03/17  18:25:03  louie * Applied suggested code from Dennis Ferguson for logical clock model based on * the equations in section 5.  Many thanks. *  * Revision 3.3.1.1  89/03/16  19:19:29  louie * Attempt to implement using the equations in section 5 of the NTP spec,  * rather then modeling the Fuzzball implementation. *  * Revision 3.3  89/03/15  14:19:45  louie * New baseline for next release. *  * Revision 3.2.1.1  89/03/15  13:47:24  louie * Use "%f" in format strings rather than "%lf". *  * Revision 3.2  89/03/07  18:22:54  louie * New version of UNIX NTP daemon and software based on the 6 March 1989 * draft of the new NTP protocol specification.  This module attempts to * conform to the new logical clock described in section 5 of the spec.  Note * that the units of the drift_compensation register have changed. *  * This version also accumulates the residual adjtime() truncation and * adds it in on subsequent adjustments. *  * Revision 3.1.1.1  89/02/15  08:55:48  louie * *** empty log message *** *  *  * Revision 3.1  89/01/30  14:43:08  louie * Second UNIX NTP test release. *  * Revision 3.0  88/12/12  16:00:38  louie * Test release of new UNIX NTP software.  This version should conform to the * revised NTP protocol specification. *  */#include <stdio.h>#include <sys/types.h>#include <sys/param.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/resource.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/udp.h>#include <arpa/inet.h>#include <netdb.h>#include <strings.h>#include <errno.h>#include <syslog.h>#include "ntp.h"#ifdef	DEBUGextern int debug;#endifextern int doset;extern int debuglevel;extern int kern_tickadj;extern char *ntoa();extern struct sysdata sys;double	drift_comp = 0.0,	compliance,	clock_adjust;long	update_timer = 0;int	adj_precision;double	adj_residual;int	firstpass = 1;#define	abs(x)	((x) < 0 ? -(x) : (x))voidinit_logical_clock(){	if (kern_tickadj)		adj_precision = kern_tickadj;	else		adj_precision = 1;	/*	 *  If you have the "fix" for adjtime() installed in you kernel, you'll	 *  have to make sure that adj_precision is set to 1 here.	 */}/* *  5.0 Logical clock procedure * *  Only paramter is an offset to vary the clock by, in seconds.  We'll either *  arrange for the clock to slew to accomodate the adjustment, or just preform *  a step adjustment if the offset is too large. * *  The update which is to be performed is left in the external *  clock_adjust.  * *  Returns non-zero if clock was reset rather than slewed. * *  Many thanks for Dennis Ferguson <dennis@gw.ccie.utoronto.ca> for his *  corrections to my code. */intadj_logical(offset)	double offset;{	struct timeval tv1, tv2;#ifdef	XADJTIME2	struct timeval delta, olddelta;#endif		/*	 *  Now adjust the logical clock	 */	if (!doset)		return 0;	adj_residual = 0.0;	if(offset > CLOCK_MAX){	/*if (offset > CLOCK_MAX || offset < -CLOCK_MAX) {*/		double steptime = offset;		(void) gettimeofday(&tv2, (struct timezone *) 0);		steptime += tv2.tv_sec;		steptime += tv2.tv_usec / 1000000.0;		tv1.tv_sec = steptime;		tv1.tv_usec = (steptime - tv1.tv_sec) * 1000000;#ifdef	DEBUG		if (debug > 2) {			steptime = (tv1.tv_sec + tv1.tv_usec/1000000.0) -				(tv2.tv_sec + tv2.tv_usec/1000000.0);			printf("adj_logical: %f %f\n", offset, steptime);		}#endif		if (settimeofday(&tv1, (struct timezone *) 0) < 0) {			syslog(LOG_ERR, "Can't set time: %m");			return(-1);		}		clock_adjust = 0.0;		firstpass = 1;		update_timer = 0;		return (1);	  /* indicate that step adjustment was done */	} else 	{		double ai;		/*		 * If this is our very first adjustment, don't touch		 * the drift compensation (this is f in the spec		 * equations), else update using the *old* value		 * of the compliance.		 */		clock_adjust = offset;		if (firstpass)			firstpass = 0;		else if (update_timer > 0) {			ai = abs(compliance);			ai = (double)(1<<CLOCK_COMP) - 				(double)(1<<CLOCK_FACTOR) * ai;			if (ai < 1.0)		/* max(... , 1.0) */				ai = 1.0;			drift_comp += offset / (ai * (double)update_timer);		}		/*		 * Set the timer to zero.  adj_host_clock() increments it		 * so we can tell the period between updates.		 */		update_timer = 0;		/*		 * Now update the compliance.  The compliance is h in the		 * equations.		 */		compliance += (offset - compliance)/(double)(1<<CLOCK_TRACK);#ifdef XADJTIME2		delta.tv_sec = offset;		delta.tv_usec = (offset - delta.tv_sec) * 1000;		(void) adjtime2(&delta, &olddelta);#endif		return(0);	}}#ifndef	XADJTIME2extern int adjtime();/* *  This is that routine that performs the periodic clock adjustment. *  The procedure is best described in the the NTP document.  In a *  nutshell, we prefer to do lots of small evenly spaced adjustments. *  The alternative, one large adjustment, creates two much of a *  clock disruption and as a result oscillation. * *  This function is called every 2**CLOCK_ADJ seconds. * *//* * global for debugging? */double adjustment;voidadj_host_clock(){	struct timeval delta, olddelta;	if (!doset)		return;	/*	 * Add update period into timer so we know how long it	 * took between the last update and the next one.	 */	update_timer += 1<<CLOCK_ADJ;	/*	 * Should check to see if update_timer > 1 day here?	 */	/*	 * Compute phase part of adjustment here and update clock_adjust.	 * Note that the equations used here are implicit in the last	 * two equations in the spec (in particular, look at the equation	 * for g and figure out how to  find the k==1 term given the k==0 term.)	 */	adjustment = clock_adjust / (double)(1<<CLOCK_PHASE);	clock_adjust -= adjustment;	/*	 * Now add in the frequency component.  Be careful to note that	 * the ni occurs in the last equation since those equations take	 * you from 64 second update to 64 second update (ei is the total	 * adjustment done over 64 seconds) and we're only deal in the	 * little 4 second adjustment interval here.	 */	adjustment += drift_comp / (double)(1<<CLOCK_FREQ);	/*	 * Add in old adjustment residual	 */	adjustment += adj_residual;	/*	 * Simplify.  Adjustment shouldn't be bigger than 2 ms.  Hope	 * writer of spec was truth telling.	 */#ifdef	DEBUG	delta.tv_sec = adjustment;	if (debug && delta.tv_sec) abort();#else	delta.tv_sec = 0;#endif	delta.tv_usec = ((long)(adjustment * 1000000.0) / adj_precision)		   * adj_precision;	adj_residual = adjustment - (double) delta.tv_usec / 1000000.0;	if (delta.tv_usec == 0)		return;	if (adjtime(&delta, &olddelta) < 0)		syslog(LOG_ERR, "Can't adjust time: %m");#ifdef	DEBUG	if(debug > 2)		printf("adj: %ld us  %f %f\n",		       delta.tv_usec, drift_comp, clock_adjust);#endif}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?