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

📄 tclwintime.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tclWinTime.c -- * *	Contains Windows specific versions of Tcl functions that *	obtain time values from the operating system. * * Copyright 1995-1998 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinTime.c,v 1.11 2002/10/09 23:57:25 kennykb Exp $ */#include "tclWinInt.h"#define SECSPERDAY (60L * 60L * 24L)#define SECSPERYEAR (SECSPERDAY * 365L)#define SECSPER4YEAR (SECSPERYEAR * 4L + SECSPERDAY)/* * The following arrays contain the day of year for the last day of * each month, where index 1 is January. */static int normalDays[] = {    -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};static int leapDays[] = {    -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};typedef struct ThreadSpecificData {    char tzName[64];		/* Time zone name */    struct tm tm;		/* time information */} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * Calibration interval for the high-resolution timer, in msec */static CONST unsigned long clockCalibrateWakeupInterval = 10000;				/* FIXME: 10 s -- should be about 10 min! *//* * Data for managing high-resolution timers. */typedef struct TimeInfo {    CRITICAL_SECTION cs;	/* Mutex guarding this structure */    int initialized;		/* Flag == 1 if this structure is				 * initialized. */    int perfCounterAvailable;	/* Flag == 1 if the hardware has a				 * performance counter */    HANDLE calibrationThread;	/* Handle to the thread that keeps the				 * virtual clock calibrated. */    HANDLE readyEvent;		/* System event used to				 * trigger the requesting thread				 * when the clock calibration procedure				 * is initialized for the first time */    HANDLE exitEvent; 		/* Event to signal out of an exit handler				 * to tell the calibration loop to				 * terminate */    /*     * The following values are used for calculating virtual time.     * Virtual time is always equal to:     *    lastFileTime + (current perf counter - lastCounter)      *				* 10000000 / curCounterFreq     * and lastFileTime and lastCounter are updated any time that     * virtual time is returned to a caller.     */    ULARGE_INTEGER lastFileTime;    LARGE_INTEGER lastCounter;    LARGE_INTEGER curCounterFreq;    /*      * The next two values are used only in the calibration thread, to track     * the frequency of the performance counter.     */    LONGLONG lastPerfCounter;	/* Performance counter the last time				 * that UpdateClockEachSecond was called */    LONGLONG lastSysTime;	/* System clock at the last time				 * that UpdateClockEachSecond was called */    LONGLONG estPerfCounterFreq;				/* Current estimate of the counter frequency				 * using the system clock as the standard */} TimeInfo;static TimeInfo timeInfo = {    { NULL },     0,     0,     (HANDLE) NULL,     (HANDLE) NULL,     (HANDLE) NULL,     0,     0,     0,     0,     0,    0};CONST static FILETIME posixEpoch = { 0xD53E8000, 0x019DB1DE };    /* * Declarations for functions defined later in this file. */static struct tm *	ComputeGMT _ANSI_ARGS_((const time_t *tp));static void		StopCalibration _ANSI_ARGS_(( ClientData ));static DWORD WINAPI     CalibrationThread _ANSI_ARGS_(( LPVOID arg ));static void 		UpdateTimeEachSecond _ANSI_ARGS_(( void ));/* *---------------------------------------------------------------------- * * TclpGetSeconds -- * *	This procedure returns the number of seconds from the epoch. *	On most Unix systems the epoch is Midnight Jan 1, 1970 GMT. * * Results: *	Number of seconds from the epoch. * * Side effects: *	None. * *---------------------------------------------------------------------- */unsigned longTclpGetSeconds(){    Tcl_Time t;    Tcl_GetTime( &t );    return t.sec;}/* *---------------------------------------------------------------------- * * TclpGetClicks -- * *	This procedure returns a value that represents the highest *	resolution clock available on the system.  There are no *	guarantees on what the resolution will be.  In Tcl we will *	call this value a "click".  The start time is also system *	dependant. * * Results: *	Number of clicks from some start time. * * Side effects: *	None. * *---------------------------------------------------------------------- */unsigned longTclpGetClicks(){    /*     * Use the Tcl_GetTime abstraction to get the time in microseconds,     * as nearly as we can, and return it.     */    Tcl_Time now;		/* Current Tcl time */    unsigned long retval;	/* Value to return */    Tcl_GetTime( &now );    retval = ( now.sec * 1000000 ) + now.usec;    return retval;}/* *---------------------------------------------------------------------- * * TclpGetTimeZone -- * *	Determines the current timezone.  The method varies wildly *	between different Platform implementations, so its hidden in *	this function. * * Results: *	Minutes west of GMT. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTclpGetTimeZone (currentTime)    unsigned long  currentTime;{    int timeZone;    tzset();    timeZone = _timezone / 60;    return timeZone;}/* *---------------------------------------------------------------------- * * Tcl_GetTime -- * *	Gets the current system time in seconds and microseconds *	since the beginning of the epoch: 00:00 UCT, January 1, 1970. * * Results: *	Returns the current time in timePtr. * * Side effects: *	On the first call, initializes a set of static variables to *	keep track of the base value of the performance counter, the *	corresponding wall clock (obtained through ftime) and the *	frequency of the performance counter.  Also spins a thread *	whose function is to wake up periodically and monitor these *	values, adjusting them as necessary to correct for drift *	in the performance counter's oscillator. * *---------------------------------------------------------------------- */voidTcl_GetTime(timePtr)    Tcl_Time *timePtr;		/* Location to store time information. */{	    struct timeb t;    /* Initialize static storage on the first trip through. */    /*     * Note: Outer check for 'initialized' is a performance win     * since it avoids an extra mutex lock in the common case.     */    if ( !timeInfo.initialized ) { 	TclpInitLock();	if ( !timeInfo.initialized ) {	    timeInfo.perfCounterAvailable		= QueryPerformanceFrequency( &timeInfo.curCounterFreq );	    /*	     * Some hardware abstraction layers use the CPU clock	     * in place of the real-time clock as a performance counter	     * reference.  This results in:	     *    - inconsistent results among the processors on	     *      multi-processor systems.	     *    - unpredictable changes in performance counter frequency	     *      on "gearshift" processors such as Transmeta and	     *      SpeedStep.	     *	     * There seems to be no way to test whether the performance	     * counter is reliable, but a useful heuristic is that	     * if its frequency is 1.193182 MHz or 3.579545 MHz, it's	     * derived from a colorburst crystal and is therefore	     * the RTC rather than the TSC.	     *	     * A sloppier but serviceable heuristic is that the RTC crystal	     * is normally less than 15 MHz while the TSC crystal is	     * virtually assured to be greater than 100 MHz.  Since Win98SE	     * appears to fiddle with the definition of the perf counter	     * frequency (perhaps in an attempt to calibrate the clock?)	     * we use the latter rule rather than an exact match.	     */	    if ( timeInfo.perfCounterAvailable		 /* The following lines would do an exact match on		  * crystal frequency:		  * && timeInfo.curCounterFreq.QuadPart != (LONGLONG) 1193182		  * && timeInfo.curCounterFreq.QuadPart != (LONGLONG) 3579545		  */		 && timeInfo.curCounterFreq.QuadPart > (LONGLONG) 15000000 ) {		timeInfo.perfCounterAvailable = FALSE;	    }	    /*	     * If the performance counter is available, start a thread to	     * calibrate it.	     */	    if ( timeInfo.perfCounterAvailable ) {		DWORD id;		InitializeCriticalSection( &timeInfo.cs );		timeInfo.readyEvent = CreateEvent( NULL, FALSE, FALSE, NULL );		timeInfo.exitEvent = CreateEvent( NULL, FALSE, FALSE, NULL );		timeInfo.calibrationThread = CreateThread( NULL,							   8192,							   CalibrationThread,							   (LPVOID) NULL,							   0,							   &id );		SetThreadPriority( timeInfo.calibrationThread,				   THREAD_PRIORITY_HIGHEST );		/*		 * Wait for the thread just launched to start running,		 * and create an exit handler that kills it so that it		 * doesn't outlive unloading tclXX.dll		 */		WaitForSingleObject( timeInfo.readyEvent, INFINITE );		CloseHandle( timeInfo.readyEvent );		Tcl_CreateExitHandler( StopCalibration, (ClientData) NULL );	    }	    timeInfo.initialized = TRUE;	}	TclpInitUnlock();    }    if ( timeInfo.perfCounterAvailable ) {		/*	 * Query the performance counter and use it to calculate the	 * current time.	 */	LARGE_INTEGER curCounter;				/* Current performance counter */	LONGLONG curFileTime;				/* Current estimated time, expressed				 * as 100-ns ticks since the Windows epoch */	static LARGE_INTEGER posixEpoch;				/* Posix epoch expressed as 100-ns ticks				 * since the windows epoch */	LONGLONG usecSincePosixEpoch;				/* Current microseconds since Posix epoch */	posixEpoch.LowPart = 0xD53E8000;	posixEpoch.HighPart = 0x019DB1DE;	EnterCriticalSection( &timeInfo.cs );	QueryPerformanceCounter( &curCounter );	curFileTime = timeInfo.lastFileTime.QuadPart	    + ( ( curCounter.QuadPart - timeInfo.lastCounter.QuadPart )		* 10000000 / timeInfo.curCounterFreq.QuadPart );	timeInfo.lastFileTime.QuadPart = curFileTime;	timeInfo.lastCounter.QuadPart = curCounter.QuadPart;	usecSincePosixEpoch = ( curFileTime - posixEpoch.QuadPart ) / 10;	timePtr->sec = (time_t) ( usecSincePosixEpoch / 1000000 );	timePtr->usec = (unsigned long ) ( usecSincePosixEpoch % 1000000 );		LeaveCriticalSection( &timeInfo.cs );	    } else {		/* High resolution timer is not available.  Just use ftime */		ftime(&t);	timePtr->sec = t.time;	timePtr->usec = t.millitm * 1000;    }}/* *---------------------------------------------------------------------- * * StopCalibration -- * *	Turns off the calibration thread in preparation for exiting the *	process. * * Results: *	None. * * Side effects: *	Sets the 'exitEvent' event in the 'timeInfo' structure to ask *	the thread in question to exit, and waits for it to do so. * *---------------------------------------------------------------------- */static voidStopCalibration( ClientData unused )				/* Client data is unused */{    SetEvent( timeInfo.exitEvent );    WaitForSingleObject( timeInfo.calibrationThread, INFINITE );    CloseHandle( timeInfo.exitEvent );    CloseHandle( timeInfo.calibrationThread );}/* *---------------------------------------------------------------------- * * TclpGetTZName -- * *	Gets the current timezone string. * * Results: *	Returns a pointer to a static string, or NULL on failure. * * Side effects: *	None. * *---------------------------------------------------------------------- */char *TclpGetTZName(int dst){    int len;    char *zone, *p;    TIME_ZONE_INFORMATION tz;    Tcl_Encoding encoding;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    char *name = tsdPtr->tzName;    /*     * tzset() under Borland doesn't seem to set up tzname[] at all.     * tzset() under MSVC has the following weird observed behavior:     *	 First time we call "clock format [clock seconds] -format %Z -gmt 1"     *	 we get "GMT", but on all subsequent calls we get the current time      *	 zone string, even though env(TZ) is GMT and the variable _timezone      *   is 0.     */    name[0] = '\0';    zone = getenv("TZ");    if (zone != NULL) {	/*	 * TZ is of form "NST-4:30NDT", where "NST" would be the	 * name of the standard time zone for this area, "-4:30" is	 * the offset from GMT in hours, and "NDT is the name of 	 * the daylight savings time zone in this area.  The offset 	 * and DST strings are optional.	 */	len = strlen(zone);	if (len > 3) {	    len = 3;	}	if (dst != 0) {	    /*

⌨️ 快捷键说明

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