diff options
Diffstat (limited to 'unix/tclUnixTime.c')
| -rw-r--r-- | unix/tclUnixTime.c | 237 | 
1 files changed, 96 insertions, 141 deletions
| diff --git a/unix/tclUnixTime.c b/unix/tclUnixTime.c index 12ba965..6a73ac2 100644 --- a/unix/tclUnixTime.c +++ b/unix/tclUnixTime.c @@ -8,14 +8,13 @@   *   * 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.26 2005/11/02 23:26:50 dkf Exp $   */  #include "tclInt.h"  #include <locale.h> -#define TM_YEAR_BASE 1900 -#define IsLeapYear(x)	(((x)%4 == 0) && ((x)%100 != 0 || (x)%400 == 0)) +#if defined(TCL_WIDE_CLICKS) && defined(MAC_OSX_TCL) +#include <mach/mach_time.h> +#endif  /*   * TclpGetDate is coded to return a pointer to a 'struct tm'. For thread @@ -23,8 +22,9 @@   * variable is the key to this buffer.   */ +#ifndef TCL_NO_DEPRECATED  static Tcl_ThreadDataKey tmKey; -typedef struct ThreadSpecificData { +typedef struct {      struct tm gmtime_buf;      struct tm localtime_buf;  } ThreadSpecificData; @@ -46,6 +46,8 @@ static char *lastTZ = NULL;	/* Holds the last setting of the TZ  static void		SetTZIfNecessary(void);  static void		CleanupMemory(ClientData clientData); +#endif /* TCL_NO_DEPRECATED */ +  static void		NativeScaleTime(Tcl_Time *timebuf,  			    ClientData clientData);  static void		NativeGetTime(Tcl_Time *timebuf, @@ -60,7 +62,7 @@ Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;  ClientData tclTimeClientData = NULL;  /* - *----------------------------------------------------------------------------- + *----------------------------------------------------------------------   *   * TclpGetSeconds --   * @@ -73,7 +75,7 @@ ClientData tclTimeClientData = NULL;   * Side effects:   *	None.   * - *----------------------------------------------------------------------------- + *----------------------------------------------------------------------   */  unsigned long @@ -83,7 +85,7 @@ TclpGetSeconds(void)  }  /* - *----------------------------------------------------------------------------- + *----------------------------------------------------------------------   *   * TclpGetClicks --   * @@ -98,7 +100,7 @@ TclpGetSeconds(void)   * Side effects:   *	None.   * - *----------------------------------------------------------------------------- + *----------------------------------------------------------------------   */  unsigned long @@ -110,7 +112,7 @@ TclpGetClicks(void)      if (tclGetTimeProcPtr != NativeGetTime) {  	Tcl_Time time; -	(*tclGetTimeProcPtr) (&time, tclTimeClientData); +	tclGetTimeProcPtr(&time, tclTimeClientData);  	now = time.sec*1000000 + time.usec;      } else {  	/* @@ -123,24 +125,26 @@ TclpGetClicks(void)  #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(void)   *----------------------------------------------------------------------   */ -int -TclpGetTimeZone( -    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. -     */ +    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. + * + *---------------------------------------------------------------------- + */ -    SetTZIfNecessary(); +double +TclpWideClicksToNanoseconds( +    Tcl_WideInt clicks) +{ +    double nsec; -    /* -     * Note: this is not a typo in "timezone" below! See tzset documentation -     * for details. -     */ +    if (tclGetTimeProcPtr != NativeGetTime) { +	nsec = clicks * 1000; +    } else { +#ifdef MAC_OSX_TCL +	static mach_timebase_info_data_t tb; +	static uint64_t maxClicksForUInt64; -    timeZone = timezone / 60; +	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 */  /*   *---------------------------------------------------------------------- @@ -270,7 +245,7 @@ void  Tcl_GetTime(      Tcl_Time *timePtr)		/* Location to store time information. */  { -    (*tclGetTimeProcPtr) (timePtr, tclTimeClientData); +    tclGetTimeProcPtr(timePtr, tclTimeClientData);  }  /* @@ -291,9 +266,10 @@ Tcl_GetTime(   *----------------------------------------------------------------------   */ +#ifndef TCL_NO_DEPRECATED  struct tm *  TclpGetDate( -    CONST time_t *time, +    const time_t *time,      int useGMT)  {      if (useGMT) { @@ -308,8 +284,7 @@ TclpGetDate(   *   * 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. @@ -322,7 +297,7 @@ TclpGetDate(  struct tm *  TclpGmtime( -    CONST time_t *timePtr)	/* Pointer to the number of seconds since the +    const time_t *timePtr)	/* Pointer to the number of seconds since the  				 * local system's epoch */  {      /* @@ -332,26 +307,14 @@ TclpGmtime(      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( -    CONST time_t *timePtr) -{ -    return TclpGmtime(timePtr); +    return &tsdPtr->gmtime_buf;  }  /* @@ -373,7 +336,7 @@ TclpGmtime_unix(  struct tm *  TclpLocaltime( -    CONST time_t *timePtr)	/* Pointer to the number of seconds since the +    const time_t *timePtr)	/* Pointer to the number of seconds since the  				 * local system's epoch */  {      /* @@ -384,25 +347,16 @@ TclpLocaltime(      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( -    CONST time_t *timePtr) -{ -    return TclpLocaltime(timePtr); +    return &tsdPtr->localtime_buf;  } +#endif /* TCL_NO_DEPRECATED */  /*   *---------------------------------------------------------------------- @@ -513,9 +467,8 @@ NativeGetTime(      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;  } @@ -538,10 +491,11 @@ NativeGetTime(   *----------------------------------------------------------------------   */ +#ifndef TCL_NO_DEPRECATED  static void  SetTZIfNecessary(void)  { -    CONST char *newTZ = getenv("TZ"); +    const char *newTZ = getenv("TZ");      Tcl_MutexLock(&tmMutex);      if (newTZ == NULL) { @@ -550,11 +504,11 @@ SetTZIfNecessary(void)      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); @@ -581,8 +535,9 @@ static void  CleanupMemory(      ClientData ignored)  { -    Tcl_Free(lastTZ); +    ckfree(lastTZ);  } +#endif /* TCL_NO_DEPRECATED */  /*   * Local Variables: | 
