summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclInt.h10
-rw-r--r--win/tclWinTime.c107
2 files changed, 103 insertions, 14 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h
index fb0bcb7..3c21de0 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -3186,6 +3186,7 @@ MODULE_SCOPE int TclpLoadMemory(Tcl_Interp *interp, void *buffer,
MODULE_SCOPE void TclInitThreadStorage(void);
MODULE_SCOPE void TclFinalizeThreadDataThread(void);
MODULE_SCOPE void TclFinalizeThreadStorage(void);
+
#ifdef TCL_WIDE_CLICKS
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double TclpWideClicksToNanoseconds(Tcl_WideInt clicks);
@@ -3194,17 +3195,12 @@ MODULE_SCOPE double TclpWideClickInMicrosec(void);
# ifdef _WIN32
# define TCL_WIDE_CLICKS 1
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
+MODULE_SCOPE double TclpWideClickInMicrosec(void);
# define TclpWideClicksToNanoseconds(clicks) \
- ((double)(clicks) * 1000)
-# define TclpWideClickInMicrosec() (1)
+ ((double)(clicks) * TclpWideClickInMicrosec() * 1000)
# endif
#endif
-#ifndef _WIN32
MODULE_SCOPE Tcl_WideInt TclpGetMicroseconds(void);
-#else
-# define TclpGetMicroseconds() \
- TclpGetWideClicks()
-#endif
MODULE_SCOPE int TclZlibInit(Tcl_Interp *interp);
MODULE_SCOPE void * TclpThreadCreateKey(void);
diff --git a/win/tclWinTime.c b/win/tclWinTime.c
index 06ea6cd..7cbc1ba 100644
--- a/win/tclWinTime.c
+++ b/win/tclWinTime.c
@@ -110,6 +110,17 @@ static TimeInfo timeInfo = {
};
/*
+ * Scale to convert wide click values from the TclpGetWideClicks native
+ * resolution to microsecond resolution and back.
+ */
+static struct {
+ int initialized; /* 1 if initialized, 0 otherwise */
+ int perfCounter; /* 1 if performance counter usable for wide clicks */
+ double microsecsScale; /* Denominator scale between clock / microsecs */
+} wideClick = {0, 0.0};
+
+
+/*
* Declarations for functions defined later in this file.
*/
@@ -221,7 +232,7 @@ TclpGetClicks(void)
* resolution clock in microseconds available on the system.
*
* Results:
- * Number of microseconds (from the epoch).
+ * Number of microseconds (from some start time).
*
* Side effects:
* This should be used for time-delta resp. for measurement purposes
@@ -234,6 +245,87 @@ TclpGetClicks(void)
Tcl_WideInt
TclpGetWideClicks(void)
{
+ LARGE_INTEGER curCounter;
+
+ if (!wideClick.initialized) {
+ LARGE_INTEGER perfCounterFreq;
+
+ /*
+ * The frequency of the performance counter is fixed at system boot and
+ * is consistent across all processors. Therefore, the frequency need
+ * only be queried upon application initialization.
+ */
+ if (QueryPerformanceFrequency(&perfCounterFreq)) {
+ wideClick.perfCounter = 1;
+ wideClick.microsecsScale = 1000000.0 / perfCounterFreq.QuadPart;
+ } else {
+ /* fallback using microseconds */
+ wideClick.perfCounter = 0;
+ wideClick.microsecsScale = 1;
+ }
+
+ wideClick.initialized = 1;
+ }
+ if (wideClick.perfCounter) {
+ if (QueryPerformanceCounter(&curCounter)) {
+ return (Tcl_WideInt)curCounter.QuadPart;
+ }
+ /* fallback using microseconds */
+ wideClick.perfCounter = 0;
+ wideClick.microsecsScale = 1;
+ return TclpGetMicroseconds();
+ } else {
+ return TclpGetMicroseconds();
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpWideClickInMicrosec --
+ *
+ * This procedure return scale to convert wide click values from the
+ * TclpGetWideClicks native resolution to microsecond resolution
+ * and back.
+ *
+ * Results:
+ * 1 click in microseconds as double.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+TclpWideClickInMicrosec(void)
+{
+ if (!wideClick.initialized) {
+ (void)TclpGetWideClicks(); /* initialize */
+ }
+ return wideClick.microsecsScale;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TclpGetMicroseconds --
+ *
+ * This procedure returns a WideInt value that represents the highest
+ * resolution clock in microseconds available on the system.
+ *
+ * Results:
+ * Number of microseconds (from the epoch).
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_WideInt
+TclpGetMicroseconds(void)
+{
Tcl_WideInt usecSincePosixEpoch;
/* Try to use high resolution timer */
@@ -346,6 +438,9 @@ NativeScaleTime(
static Tcl_WideInt
NativeGetMicroseconds(void)
{
+ static LARGE_INTEGER posixEpoch;
+ /* Posix epoch expressed as 100-ns ticks since
+ * the windows epoch. */
/*
* Initialize static storage on the first trip through.
*
@@ -356,6 +451,10 @@ NativeGetMicroseconds(void)
if (!timeInfo.initialized) {
TclpInitLock();
if (!timeInfo.initialized) {
+
+ posixEpoch.LowPart = 0xD53E8000;
+ posixEpoch.HighPart = 0x019DB1DE;
+
timeInfo.perfCounterAvailable =
QueryPerformanceFrequency(&timeInfo.nominalFreq);
@@ -468,15 +567,9 @@ NativeGetMicroseconds(void)
/* Current performance counter. */
Tcl_WideInt 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. */
Tcl_WideInt usecSincePosixEpoch;
/* Current microseconds since Posix epoch. */
- posixEpoch.LowPart = 0xD53E8000;
- posixEpoch.HighPart = 0x019DB1DE;
-
QueryPerformanceCounter(&curCounter);
/*