Add rts time util getUnixEpochTime
authorDuncan Coutts <duncan@well-typed.com>
Tue, 25 Oct 2011 17:41:46 +0000 (18:41 +0100)
committerDuncan Coutts <duncan@well-typed.com>
Wed, 26 Oct 2011 11:00:42 +0000 (12:00 +0100)
The other existing time utilities give us time elapsed since process
or thread start. This is for wall clock time, using the common Unix
epoch interpretation.

rts/GetTime.h
rts/posix/GetTime.c
rts/win32/GetTime.c

index 7b89c05..b8d402d 100644 (file)
@@ -22,6 +22,11 @@ Ticks getThreadCPUTime      (void);
 Ticks getProcessElapsedTime (void);
 void  getProcessTimes       (Ticks *user, Ticks *elapsed);
 
+/* Get the current date and time.
+   Uses seconds since the Unix epoch, plus nanoseconds
+ */
+void  getUnixEpochTime      (StgWord64 *sec, StgWord32 *nsec);
+
 // Not strictly timing, but related
 nat   getPageFaults         (void);
 
index 15643b8..eab7177 100644 (file)
@@ -181,6 +181,22 @@ Ticks getThreadCPUTime(void)
     return getProcessCPUTime();
 }
 
+void getUnixEpochTime(StgWord64 *sec, StgWord32 *nsec)
+{
+#if defined(HAVE_GETTIMEOFDAY)
+    struct timeval tv;
+    gettimeofday(&tv, (struct timezone *) NULL);
+    *sec  = tv.tv_sec;
+    *nsec = tv.tv_usec * 1000;
+#else
+    /* Sigh, fall back to second resolution. */
+    time_t t;
+    time(&t);
+    *sec  = t;
+    *nsec = 0;
+#endif
+}
+
 nat
 getPageFaults(void)
 {
index 9699bd6..13fb5ab 100644 (file)
@@ -92,6 +92,46 @@ getThreadCPUTime(void)
     return fileTimeToTicks(userTime);
 }
 
+void
+getUnixEpochTime(StgWord64 *sec, StgWord32 *nsec)
+{
+    /* Windows has a bunch of time APIs but none that directly give
+       us unix epoch time, so we have to do a little dance. */
+
+    SYSTEMTIME systime;
+    FILETIME filetime;
+    ULARGE_INTEGER unixtime;
+
+    /* Windows SYSTEMTIME is a big struct with fields for
+       year, month, day, hour, minute, second, millisecond. */
+    GetSystemTime(&systime);
+    /* Windows FILETIME timestamps use an epoch-based time,
+       using a 64bit unsigned word. The time is measured in
+       units of 100 nanoseconds since an epoch of 1601. */
+    SystemTimeToFileTime(&systime, &filetime);
+
+    /* FILETIME isn't directly a 64bit word, but a struct with
+       a pair of 32bit words, so we have to convert via a
+       ULARGE_INTEGER struct which is a handy union type */
+    unixtime.LowPart  = filetime.dwLowDateTime;
+    unixtime.HighPart = filetime.dwHighDateTime;
+    
+    /* We have to do an epoch conversion, since FILETIME uses 1601
+       while we want unix epoch of 1970. In case you were wondering,
+       there were 11,644,473,600 seconds between 1601 and 1970, then
+       multiply by 10^7 for units of 100 nanoseconds. */
+    unixtime.QuadPart = unixtime.QuadPart - 116444736000000000ull;
+    
+    /* For the seconds part we use integer division by 10^7 */
+    *sec  = unixtime.QuadPart / 10000000ull;
+    
+    /* The remainder from integer division by 10^7 gives us
+       the sub-second component in units of 100 nanoseconds.
+       So for nanoseconds we just multiply by 100.
+       Note that nanoseconds always fits in a 32bit word */
+    *nsec = ((unsigned long)(unixtime.QuadPart % 10000000ull)) * 100ul;
+}
+
 nat
 getPageFaults(void)
 {