diff options
Diffstat (limited to 'unix/tclUnixTime.c')
-rw-r--r-- | unix/tclUnixTime.c | 292 |
1 files changed, 122 insertions, 170 deletions
diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index 1ebec63..926e8f4 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -8,12 +8,14 @@ * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. - * - * RCS: @(#) $Id: tclUnixTime.c,v 1.25 2005/07/20 23:16:01 dkf Exp $ */ #include "tclInt.h" #include <locale.h> +#if defined(TCL_WIDE_CLICKS) && defined(MAC_OSX_TCL) +#include <mach/mach_time.h> +#endif + #define TM_YEAR_BASE 1900 #define IsLeapYear(x) (((x)%4 == 0) && ((x)%100 != 0 || (x)%400 == 0)) @@ -44,12 +46,12 @@ static char *lastTZ = NULL; /* Holds the last setting of the TZ * Static functions declared in this file. */ -static void SetTZIfNecessary _ANSI_ARGS_((void)); -static void CleanupMemory _ANSI_ARGS_((ClientData)); -static void NativeScaleTime _ANSI_ARGS_((Tcl_Time *timebuf, - ClientData clientData)); -static void NativeGetTime _ANSI_ARGS_((Tcl_Time *timebuf, - ClientData clientData)); +static void SetTZIfNecessary(void); +static void CleanupMemory(ClientData clientData); +static void NativeScaleTime(Tcl_Time *timebuf, + ClientData clientData); +static void NativeGetTime(Tcl_Time *timebuf, + ClientData clientData); /* * TIP #233 (Virtualized Time): Data for the time hooks, if any. @@ -60,7 +62,7 @@ Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime; ClientData tclTimeClientData = NULL; /* - *----------------------------------------------------------------------------- + *---------------------------------------------------------------------- * * TclpGetSeconds -- * @@ -73,17 +75,17 @@ ClientData tclTimeClientData = NULL; * Side effects: * None. * - *----------------------------------------------------------------------------- + *---------------------------------------------------------------------- */ unsigned long -TclpGetSeconds() +TclpGetSeconds(void) { - return time((time_t *) NULL); + return time(NULL); } /* - *----------------------------------------------------------------------------- + *---------------------------------------------------------------------- * * TclpGetClicks -- * @@ -98,11 +100,11 @@ TclpGetSeconds() * Side effects: * None. * - *----------------------------------------------------------------------------- + *---------------------------------------------------------------------- */ unsigned long -TclpGetClicks() +TclpGetClicks(void) { unsigned long now; @@ -110,7 +112,7 @@ TclpGetClicks() if (tclGetTimeProcPtr != NativeGetTime) { Tcl_Time time; - (*tclGetTimeProcPtr) (&time, tclTimeClientData); + tclGetTimeProcPtr(&time, tclTimeClientData); now = time.sec*1000000 + time.usec; } else { /* @@ -123,24 +125,26 @@ TclpGetClicks() #else Tcl_Time time; - (*tclGetTimeProcPtr) (&time, tclTimeClientData); + tclGetTimeProcPtr(&time, tclTimeClientData); now = time.sec*1000000 + time.usec; #endif return now; } +#ifdef TCL_WIDE_CLICKS /* *---------------------------------------------------------------------- * - * TclpGetTimeZone -- + * TclpGetWideClicks -- * - * Determines the current timezone. The method varies wildly between - * different platform implementations, so its hidden in this function. + * This procedure returns a WideInt value that represents the highest + * resolution clock available on the system. There are no garantees on + * what the resolution will be. In Tcl we will call this value a "click". + * The start time is also system dependant. * * Results: - * The return value is the local time zone, measured in minutes away from - * GMT (-ve for east, +ve for west). + * Number of WideInt clicks from some start time. * * Side effects: * None. @@ -148,103 +152,74 @@ TclpGetClicks() *---------------------------------------------------------------------- */ -int -TclpGetTimeZone(currentTime) - unsigned long currentTime; +Tcl_WideInt +TclpGetWideClicks(void) { - int timeZone; + Tcl_WideInt now; - /* - * We prefer first to use the time zone in "struct tm" if the structure - * contains such a member. Following that, we try to locate the external - * 'timezone' variable and use its value. If both of those methods fail, - * we attempt to convert a known time to local time and use the difference - * from UTC as the local time zone. In all cases, we need to undo any - * Daylight Saving Time adjustment. - */ - -#if defined(HAVE_TM_TZADJ) -#define TCL_GOT_TIMEZONE - /* - * Struct tm contains tm_tzadj - that value may be used. - */ - - time_t curTime = (time_t) currentTime; - struct tm *timeDataPtr = TclpLocaltime(&curTime); + if (tclGetTimeProcPtr != NativeGetTime) { + Tcl_Time time; - timeZone = timeDataPtr->tm_tzadj / 60; - if (timeDataPtr->tm_isdst) { - timeZone += 60; - } + tclGetTimeProcPtr(&time, tclTimeClientData); + now = (Tcl_WideInt) (time.sec*1000000 + time.usec); + } else { +#ifdef MAC_OSX_TCL + now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX); +#else +#error Wide high-resolution clicks not implemented on this platform #endif - -#if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE) -#define TCL_GOT_TIMEZONE - /* - * Struct tm contains tm_gmtoff - that value may be used. - */ - - time_t curTime = (time_t) currentTime; - struct tm *timeDataPtr = TclpLocaltime(&curTime); - - timeZone = -(timeDataPtr->tm_gmtoff / 60); - if (timeDataPtr->tm_isdst) { - timeZone += 60; } -#endif - -#if defined(HAVE_TIMEZONE_VAR) && !defined(TCL_GOT_TIMEZONE) && !defined(USE_DELTA_FOR_TZ) -#define TCL_GOT_TIMEZONE - /* - * The 'timezone' external var is present and may be used. - */ - SetTZIfNecessary(); + return now; +} + +/* + *---------------------------------------------------------------------- + * + * TclpWideClicksToNanoseconds -- + * + * This procedure converts click values from the TclpGetWideClicks native + * resolution to nanosecond resolution. + * + * Results: + * Number of nanoseconds from some start time. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ - /* - * Note: this is not a typo in "timezone" below! See tzset documentation - * for details. - */ +double +TclpWideClicksToNanoseconds( + Tcl_WideInt clicks) +{ + double nsec; - timeZone = timezone / 60; + if (tclGetTimeProcPtr != NativeGetTime) { + nsec = clicks * 1000; + } else { +#ifdef MAC_OSX_TCL + static mach_timebase_info_data_t tb; + static uint64_t maxClicksForUInt64; + + if (!tb.denom) { + mach_timebase_info(&tb); + maxClicksForUInt64 = UINT64_MAX / tb.numer; + } + if ((uint64_t) clicks < maxClicksForUInt64) { + nsec = ((uint64_t) clicks) * tb.numer / tb.denom; + } else { + nsec = ((long double) (uint64_t) clicks) * tb.numer / tb.denom; + } +#else +#error Wide high-resolution clicks not implemented on this platform #endif - -#if !defined(TCL_GOT_TIMEZONE) -#define TCL_GOT_TIMEZONE - /* - * Fallback - determine time zone with a known reference time. - */ - - time_t tt; - struct tm *stm; - - tt = 849268800L; /* 1996-11-29 12:00:00 GMT */ - stm = TclpLocaltime(&tt); /* eg 1996-11-29 6:00:00 CST6CDT */ - - /* - * The calculation below assumes a max of +12 or -12 hours from GMT. - */ - - timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min); - if (stm->tm_isdst) { - timeZone += 60; } - /* - * Now have offset for our known reference time, eg +360 for CST6CDT. - */ -#endif - -#ifndef TCL_GOT_TIMEZONE - /* - * Cause fatal compile error, we don't know how to get timezone. - */ - -#error autoconf did not figure out how to determine the timezone. -#endif - - return timeZone; + return nsec; } +#endif /* TCL_WIDE_CLICKS */ /* *---------------------------------------------------------------------- @@ -267,10 +242,10 @@ TclpGetTimeZone(currentTime) */ void -Tcl_GetTime(timePtr) - Tcl_Time *timePtr; /* Location to store time information. */ +Tcl_GetTime( + Tcl_Time *timePtr) /* Location to store time information. */ { - (*tclGetTimeProcPtr) (timePtr, tclTimeClientData); + tclGetTimeProcPtr(timePtr, tclTimeClientData); } /* @@ -292,9 +267,9 @@ Tcl_GetTime(timePtr) */ struct tm * -TclpGetDate(time, useGMT) - CONST time_t *time; - int useGMT; +TclpGetDate( + const time_t *time, + int useGMT) { if (useGMT) { return TclpGmtime(time); @@ -308,8 +283,7 @@ TclpGetDate(time, useGMT) * * TclpGmtime -- * - * Wrapper around the 'gmtime' library function to make it thread - * safe. + * Wrapper around the 'gmtime' library function to make it thread safe. * * Results: * Returns a pointer to a 'struct tm' in thread-specific data. @@ -321,8 +295,8 @@ TclpGetDate(time, useGMT) */ struct tm * -TclpGmtime(timePtr) - CONST time_t *timePtr; /* Pointer to the number of seconds since the +TclpGmtime( + const time_t *timePtr) /* Pointer to the number of seconds since the * local system's epoch */ { /* @@ -332,26 +306,14 @@ TclpGmtime(timePtr) ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&tmKey); #ifdef HAVE_GMTIME_R - gmtime_r(timePtr, &(tsdPtr->gmtime_buf)); + gmtime_r(timePtr, &tsdPtr->gmtime_buf); #else Tcl_MutexLock(&tmMutex); - memcpy((VOID *) &(tsdPtr->gmtime_buf), (VOID *) gmtime(timePtr), - sizeof(struct tm)); + memcpy(&tsdPtr->gmtime_buf, gmtime(timePtr), sizeof(struct tm)); Tcl_MutexUnlock(&tmMutex); #endif - return &(tsdPtr->gmtime_buf); -} - -/* - * Forwarder for obsolete item in Stubs - */ - -struct tm* -TclpGmtime_unix(timePtr) - CONST time_t *timePtr; -{ - return TclpGmtime(timePtr); + return &tsdPtr->gmtime_buf; } /* @@ -372,8 +334,8 @@ TclpGmtime_unix(timePtr) */ struct tm * -TclpLocaltime(timePtr) - CONST time_t *timePtr; /* Pointer to the number of seconds since the +TclpLocaltime( + const time_t *timePtr) /* Pointer to the number of seconds since the * local system's epoch */ { /* @@ -384,24 +346,14 @@ TclpLocaltime(timePtr) SetTZIfNecessary(); #ifdef HAVE_LOCALTIME_R - localtime_r(timePtr, &(tsdPtr->localtime_buf)); + localtime_r(timePtr, &tsdPtr->localtime_buf); #else Tcl_MutexLock(&tmMutex); - memcpy((VOID *) &(tsdPtr->localtime_buf), (VOID *) localtime(timePtr), - sizeof(struct tm)); + memcpy(&tsdPtr->localtime_buf, localtime(timePtr), sizeof(struct tm)); Tcl_MutexUnlock(&tmMutex); #endif - return &(tsdPtr->localtime_buf); -} -/* - * Forwarder for obsolete item in Stubs - */ -struct tm* -TclpLocaltime_unix(timePtr) - CONST time_t *timePtr; -{ - return TclpLocaltime(timePtr); + return &tsdPtr->localtime_buf; } /* @@ -422,10 +374,10 @@ TclpLocaltime_unix(timePtr) */ void -Tcl_SetTimeProc(getProc, scaleProc, clientData) - Tcl_GetTimeProc *getProc; - Tcl_ScaleTimeProc *scaleProc; - ClientData clientData; +Tcl_SetTimeProc( + Tcl_GetTimeProc *getProc, + Tcl_ScaleTimeProc *scaleProc, + ClientData clientData) { tclGetTimeProcPtr = getProc; tclScaleTimeProcPtr = scaleProc; @@ -449,10 +401,10 @@ Tcl_SetTimeProc(getProc, scaleProc, clientData) */ void -Tcl_QueryTimeProc(getProc, scaleProc, clientData) - Tcl_GetTimeProc **getProc; - Tcl_ScaleTimeProc **scaleProc; - ClientData *clientData; +Tcl_QueryTimeProc( + Tcl_GetTimeProc **getProc, + Tcl_ScaleTimeProc **scaleProc, + ClientData *clientData) { if (getProc) { *getProc = tclGetTimeProcPtr; @@ -483,9 +435,9 @@ Tcl_QueryTimeProc(getProc, scaleProc, clientData) */ static void -NativeScaleTime(timePtr, clientData) - Tcl_Time *timePtr; - ClientData clientData; +NativeScaleTime( + Tcl_Time *timePtr, + ClientData clientData) { /* Native scale is 1:1. Nothing is done */ } @@ -508,14 +460,13 @@ NativeScaleTime(timePtr, clientData) */ static void -NativeGetTime(timePtr, clientData) - Tcl_Time *timePtr; - ClientData clientData; +NativeGetTime( + Tcl_Time *timePtr, + ClientData clientData) { struct timeval tv; - struct timezone tz; - (void) gettimeofday(&tv, &tz); + (void) gettimeofday(&tv, NULL); timePtr->sec = tv.tv_sec; timePtr->usec = tv.tv_usec; } @@ -539,9 +490,9 @@ NativeGetTime(timePtr, clientData) */ static void -SetTZIfNecessary() +SetTZIfNecessary(void) { - CONST char *newTZ = getenv("TZ"); + const char *newTZ = getenv("TZ"); Tcl_MutexLock(&tmMutex); if (newTZ == NULL) { @@ -550,11 +501,11 @@ SetTZIfNecessary() if (lastTZ == NULL || strcmp(lastTZ, newTZ)) { tzset(); if (lastTZ == NULL) { - Tcl_CreateExitHandler(CleanupMemory, (ClientData) NULL); + Tcl_CreateExitHandler(CleanupMemory, NULL); } else { - Tcl_Free(lastTZ); + ckfree(lastTZ); } - lastTZ = Tcl_Alloc(strlen(newTZ) + 1); + lastTZ = ckalloc(strlen(newTZ) + 1); strcpy(lastTZ, newTZ); } Tcl_MutexUnlock(&tmMutex); @@ -578,9 +529,10 @@ SetTZIfNecessary() */ static void -CleanupMemory(ClientData ignored) +CleanupMemory( + ClientData ignored) { - Tcl_Free(lastTZ); + ckfree(lastTZ); } /* |