⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nt_clockstuff.c

📁 基于ntp协议的网络时间服务程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Windows NT Clock Routines * * * Revision History: * $Log$ * Revision 1.9  2000/11/19 09:02:12  dietrich * From: Ron Thornton [rthornto@pictel.com] * Sent: Thu 11/16/00 8:51 AM * On Windows 2000 it requires a privilege on the current process token * that is disabled by default on Windows 2000. * * I set the token by adding the following code at the beginning of the * init_winnt_time() function in nt_clockstuff.c. * * Revision 1.8  2000/11/19 08:03:20  dietrich * From: "Colin Dancer" <colin.dancer@pyrochrome.net> * To: <bugs@ntp.org> * Sent: 10 November 2000 12:59 * Subject: NT bug in NTP 4.0.99j * * I've found a bug in (and produced a fix for) the NT clock interpolation * code in NTP 4.0.99j. * * The symptoms of the problem are that gettimeofday() function on NT * can be wrong by hundreds of seconds if, while a gettimeofday() call * is being processed, an APC completes after the query of the performance * counter but before the lock is grabbed.  The most obvious fix is to move * the lock to include the querying of the performance counter, but this * could affect the predictability of the timestamp so I have instead * tweaked the code to detect and sidestep the duff calculation. * * I've also found that on a loaded system the execution of the APC can be * delayed, leading to errors of upto 10ms.  There is no easy fix to this, * but I do have code for an alternative interpolation scheme which avoids * the problem on single processor systems. I'm currently integrating this * along with code for deciding which algorithm to use based on whether * the system is SP or MP. * * Created by Sven Dietrich  sven@inter-yacht.com * */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "ntp_stdlib.h"#include "clockstuff.h"#include "ntservice.h"#include "ntp_timer.h"#include "ntpd.h"/* * Include code to possibly modify the MM timer while the service is active.  */  /*   * Whether or not MM timer modifications takes place is still controlled    * by the variable below which is initialized by a default value but    * might be changed depending on a command line switch.   */  int modify_mm_timer = MM_TIMER_LORES;  #define MM_TIMER_INTV   1  /* the interval we'd want to set the MM timer to [ms] */  static UINT wTimerRes;  static TIMECAPS tc;extern double sys_residual;	/* residual from previous adjustment */char szMsgPath[255];BOOL init_randfile();static long last_Adj = 0;#define LS_CORR_INTV_SECS  2   /* seconds to apply leap second correction */#define LS_CORR_INTV   ( (LONGLONG) HECTONANOSECONDS * LS_CORR_INTV_SECS )  #define LS_CORR_LIMIT  ( (LONGLONG) HECTONANOSECONDS / 2 )  // half a secondtypedef union{	FILETIME ft;	ULONGLONG ull;} FT_ULL;static FT_ULL ls_ft;static DWORD ls_time_adjustment;static LARGE_INTEGER ls_ref_perf_cnt;static LONGLONG ls_elapsed;static void StartClockThread(void);static void StopClockThread(void);static CRITICAL_SECTION TimerCritialSection; /* lock for LastTimerCount & LastTimerTime */static ULONGLONG RollOverCount = 0;static ULONGLONG LastTimerCount = 0;static ULONGLONG LastTimerTime = 0;static HANDLE ClockThreadHandle = NULL;static HANDLE TimerThreadExitRequest = NULL;static DWORD every = 0;static DWORD initial_units_per_tick = 0;static DWORD lastLowTimer = 0;ULONGLONG PerfFrequency = 0;static DWORD units_per_tick = 0;static DOUBLE ppm_per_adjust_unit = 0.0;/* * Request Multimedia Timer */voidset_mm_timer(int timerres){	modify_mm_timer = timerres;}/* * adj_systime - called once every second to make system time adjustments. * Returns 1 if okay, 0 if trouble. */intadj_systime(	double now	){	double dtemp;	u_char isneg = 0;	int rc;	long dwTimeAdjustment;	/*	 * Add the residual from the previous adjustment to the new	 * adjustment, bound and round.	 */	dtemp = sys_residual + now;	sys_residual = 0;	if (dtemp < 0)	{		isneg = 1;		dtemp = -dtemp;	}	if (dtemp > NTP_MAXFREQ)		dtemp = NTP_MAXFREQ;	dtemp = dtemp * 1e6;	if (isneg)		dtemp = -dtemp;	/* dtemp is in micro seconds. NT uses 100 ns units,	 * so a unit change in dwTimeAdjustment corresponds	 * to slewing 10 ppm on a 100 Hz system.	 * Calculate the number of 100ns units to add,	 * using OS tick frequency as per suggestion from Harry Pyle,	 * and leave the remainder in dtemp */	dwTimeAdjustment = (DWORD)( dtemp / ppm_per_adjust_unit + (isneg ? -0.5 : 0.5)) ;	dtemp += (double) -dwTimeAdjustment * ppm_per_adjust_unit;	  /* If a leap second is pending then determine the UTC time stamp 	 * of when the insertion must take place */	if (leap_next & LEAP_ADDSECOND)  	{		if ( ls_ft.ull == 0 )  /* time stamp has not yet been computed */		{			FT_ULL ft;			SYSTEMTIME st;			int itmp;			GetSystemTimeAsFileTime(&ft.ft);   			FileTimeToSystemTime(&ft.ft, &st); 			/* Accept leap announcement only 1 month in advance,			 * for end of March, June, September, or December.			 */			if ( ( st.wMonth % 3 ) == 0 )			{				/* The comarison time stamp is computed according 				 * to 0:00h UTC of the following day */   				if ( ++st.wMonth > 12 )				{					st.wMonth -= 12;					st.wYear++;				}								st.wDay = 1;				st.wHour = 0;				st.wMinute = 0;				st.wSecond = 0;				st.wMilliseconds = 0;				SystemTimeToFileTime(&st, &ls_ft.ft);				msyslog(LOG_INFO, "Detected positive leap second announcement "				                  "for %04d-%02d-%02d %02d:%02d:%02d UTC",													st.wYear, st.wMonth, st.wDay,				                  st.wHour, st.wMinute, st.wSecond);			}		}  }   /* If the time stamp for the next leap second has been set	 * then check if the leap second must be handled */	if ( ls_ft.ull )	{		LARGE_INTEGER this_perf_count;		QueryPerformanceCounter( &this_perf_count );		if ( ls_time_adjustment == 0 ) /* has not yet been scheduled */		{			FT_ULL curr_ft;	 		GetSystemTimeAsFileTime(&curr_ft.ft);   			if ( curr_ft.ull >= ls_ft.ull )			{				ls_time_adjustment = every / LS_CORR_INTV_SECS;				ls_ref_perf_cnt = this_perf_count;				ls_elapsed = 0;				msyslog(LOG_INFO, "Inserting positive leap second.");			}		}		else  /* leap sec adjustment has been scheduled previously */		{			ls_elapsed = ( this_perf_count.QuadPart - ls_ref_perf_cnt.QuadPart ) 			               * HECTONANOSECONDS / PerfFrequency;		}		if ( ls_time_adjustment )  /* leap second adjustment is currently active */		{			if ( ls_elapsed > ( LS_CORR_INTV - LS_CORR_LIMIT ) )			{				ls_time_adjustment = 0;  /* leap second adjustment done */				ls_ft.ull = 0;			}		/* NOTE: While the system time is slewed during the leap second 		 * the interpolation function which is based on the performance 		 * counter does not account for the slew.		 */		dwTimeAdjustment -= ls_time_adjustment;		}	}	/* only adjust the clock if adjustment changes */	if (last_Adj != dwTimeAdjustment) { 				last_Adj = dwTimeAdjustment;# ifdef DEBUG		if (debug > 1)			printf("SetSystemTimeAdjustment( %ld) + (%ld)\n", dwTimeAdjustment, units_per_tick);			# endif			dwTimeAdjustment += units_per_tick;			rc = !SetSystemTimeAdjustment(dwTimeAdjustment, FALSE);	}	else rc = 0;	if (rc)	{		msyslog(LOG_ERR, "Can't adjust time: %m");		return 0;	}	else {		sys_residual = dtemp / 1000000.0;	}#ifdef DEBUG	if (debug > 6)		printf("adj_systime: adj %.9f -> remaining residual %.9f\n", now, sys_residual);#endif	return 1;}void init_winnt_time(void){	BOOL noslew;	HANDLE hToken = INVALID_HANDLE_VALUE;	TOKEN_PRIVILEGES tkp;	/*	 * Make sure the service is initialized	 * before we do anything else	 */	ntservice_init();	/* Set the Event-ID message-file name. */	if (!GetModuleFileName(NULL, szMsgPath, sizeof(szMsgPath))) 	{		msyslog(LOG_ERR, "GetModuleFileName(PGM_EXE_FILE) failed: %m\n");		exit(1);	}	/* Initialize random file before OpenSSL checks */	if(!init_randfile())		msyslog(LOG_ERR, "Unable to initialize .rnd file\n");	/*	 * Get privileges needed for fiddling with the clock	 */	  /* get the current process token handle */	if (!OpenProcessToken(GetCurrentProcess(),	     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 	{		msyslog(LOG_ERR, "OpenProcessToken failed: %m");		exit(-1);

⌨️ 快捷键说明

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