summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixTime.c
diff options
context:
space:
mode:
Diffstat (limited to 'unix/tclUnixTime.c')
-rw-r--r--unix/tclUnixTime.c292
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);
}
/*