Move getMonotonicUSec from base to the RTS.
authorPaolo Capriotti <p.capriotti@gmail.com>
Tue, 8 May 2012 12:05:14 +0000 (13:05 +0100)
committerPaolo Capriotti <p.capriotti@gmail.com>
Tue, 8 May 2012 12:05:14 +0000 (13:05 +0100)
rts/GetTime.h
rts/Linker.c
rts/RtsStartup.c
rts/posix/GetTime.c
rts/win32/GetTime.c

index 86c5511..45804aa 100644 (file)
@@ -11,6 +11,9 @@
 
 #include "BeginPrivate.h"
 
+void initializeTimer       (void);
+StgWord64 getMonotonicNSec (void);
+
 Time getProcessCPUTime     (void);
 Time getThreadCPUTime      (void);
 Time getProcessElapsedTime (void);
index 6486d4d..c437eb0 100644 (file)
@@ -1283,6 +1283,7 @@ typedef struct _RtsSymbolVal {
       SymI_HasProto(n_capabilities)                     \
       SymI_HasProto(stg_traceCcszh)                     \
       SymI_HasProto(stg_traceEventzh)                   \
+      SymI_HasProto(getMonotonicNSec)                   \
       RTS_USER_SIGNALS_SYMBOLS                          \
       RTS_INTCHAR_SYMBOLS
 
index 307a691..ed13915 100644 (file)
@@ -128,6 +128,9 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config)
     /* Initialise the stats department, phase 0 */
     initStats0();
 
+    /* Initialize system timer before starting to collect stats */
+    initializeTimer();
+
     /* Next we do is grab the start time...just in case we're
      * collecting timing statistics.
      */
index 549b3b0..da8d0fa 100644 (file)
 // we'll implement getProcessCPUTime() and getProcessElapsedTime()
 // separately, using getrusage() and gettimeofday() respectively
 
+#ifdef darwin_HOST_OS
+static double timer_scaling_factor_ns = 0.0;
+#endif
+
+void initializeTimer()
+{
+#ifdef darwin_HOST_OS
+    mach_timebase_info_data_t info;
+    (void) mach_timebase_info(&info);
+    timer_scaling_factor_ns = (double)info.numer / (double)info.denom * 1e9;
+#endif
+}
+
 Time getProcessCPUTime(void)
 {
 #if !defined(BE_CONSERVATIVE) && defined(HAVE_CLOCK_GETTIME) && defined (_SC_CPUTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) && defined(HAVE_SYSCONF)
@@ -64,32 +77,31 @@ Time getProcessCPUTime(void)
     }
 }
 
-Time getProcessElapsedTime(void)
+StgWord64 getMonotonicNSec(void)
 {
 #ifdef HAVE_CLOCK_GETTIME
     struct timespec ts;
 
     clock_gettime(CLOCK_ID, &ts);
-    return SecondsToTime(ts.tv_sec) + NSToTime(ts.tv_nsec);
+    return (StgWord64)ts.tv_sec * 1000000000 +
+           (StgWord64)ts.tv_nsec;
 #elif defined(darwin_HOST_OS)
     uint64_t time = mach_absolute_time();
-    static double scaling_factor = 0.0;
-
-    if (scaling_factor == 0.0) {
-        mach_timebase_info_data_t info;
-        (void) mach_timebase_info(&info);
-        scaling_factor = (double)info.numer / (double)info.denom;
-    }
-
-    return (Time)((double)time * scaling_factor);
+    return (double)time * timer_scaling_factor_ns;
 #else
     struct timeval tv;
 
     gettimeofday(&tv, (struct timezone *) NULL);
-    return SecondsToTime(tv.tv_sec) + USToTime(tv.tv_usec);
+    return (StgWord64)tv.tv_sec * 1000000000 +
+           (StgWord64)tv.tv_usec * 1000;
 #endif
 }
 
+Time getProcessElapsedTime(void)
+{
+    return NSToTime(getMonotonicNSec());
+}
+
 void getProcessTimes(Time *user, Time *elapsed)
 {
     *user    = getProcessCPUTime();
index 9a322bf..ec506fe 100644 (file)
@@ -47,37 +47,57 @@ getProcessCPUTime(void)
     return fileTimeToRtsTime(userTime);
 }
 
-// getProcessElapsedTime relies on QueryPerformanceFrequency 
-// which should be available on any Windows computer thay you
-// would want to run Haskell on. Satnam Singh, 5 July 2010.
+// Number of ticks per second used by the QueryPerformanceFrequency
+// implementaiton, represented by a 64-bit union type.
+static LARGE_INTEGER qpc_frequency = {.QuadPart = 0};
+
+// Initialize qpc_frequency. This function should be called before any call to
+// getMonotonicNSec.  If QPC is not supported on this system, qpc_frequency is
+// set to 0.
+void initializeTimer()
+{
+    BOOL qpc_supported = QueryPerformanceFrequency(&qpc_frequency);
+    if (!qpc_supported)
+    {
+        qpc_frequency.QuadPart = 0;
+    }
+}
+
+HsWord64
+getMonotonicNSec()
+{
+    if (qpc_frequency.QuadPart)
+    {
+        // system_time is a 64-bit union type used to represent the
+        // tick count returned by QueryPerformanceCounter
+        LARGE_INTEGER system_time;
+
+        // get the tick count.
+        QueryPerformanceCounter(&system_time);
+
+        // compute elapsed seconds as double
+        double secs = (double)system_time.QuadPart /
+                      (double)qpc_frequency.QuadPart;
+
+        // return elapsed time in nanoseconds
+        return (HsWord64)(secs * 1e9);
+    }
+    else // fallback to GetTickCount
+    {
+        // NOTE: GetTickCount is a 32-bit millisecond value, so it wraps around
+        // every 49 days.
+        DWORD count = GetTickCount();
+
+        // getTickCount is in milliseconds, so multiply it by 1000000 to get
+        // nanoseconds.
+        return (HsWord64)count * 1000000;
+    }
+}
 
 Time
 getProcessElapsedTime(void)
 {
-    // frequency represents the number of ticks per second
-    // used by the QueryPerformanceFrequency implementaiton
-    // and is represented by a 64-bit union type initially set to 0
-    // and updated just once (hence use of static).
-    static LARGE_INTEGER frequency = {.QuadPart = 0} ;  
-
-    // system_time is a 64-bit union type used to represent the
-    // tick count returned by QueryPerformanceCounter
-    LARGE_INTEGER system_time ;
-
-    // If this is the first time we are calling getProcessElapsedTime
-    // then record the ticks per second used by QueryPerformanceCounter
-    if (frequency.QuadPart == 0) {
-      QueryPerformanceFrequency(&frequency);
-    }
-    
-    // Get the tick count.
-    QueryPerformanceCounter(&system_time) ;
-
-    // Return the tick count as a Time value.
-    // Using double to compute the intermediate value, because a 64-bit
-    // int would overflow when multiplied by TICK_RESOLUTION in about 81 days.
-    return fsecondsToTime((double)system_time.QuadPart /
-                          (double)frequency.QuadPart) ;
+    return NSToTime(getMonotonicNSec());
 }
 
 Time