Add rts time util getUnixEpochTime
[ghc.git] / rts / win32 / GetTime.c
1 /* -----------------------------------------------------------------------------
2 *
3 * (c) The GHC Team 2005
4 *
5 * Machine-dependent time measurement functions
6 *
7 * ---------------------------------------------------------------------------*/
8
9 #include "Rts.h"
10 #include "GetTime.h"
11
12 #include <windows.h>
13
14 #ifdef HAVE_TIME_H
15 # include <time.h>
16 #endif
17
18 #define HNS_PER_SEC 10000000LL /* FILETIMES are in units of 100ns */
19 /* Convert FILETIMEs into secs */
20
21 static INLINE_ME Ticks
22 fileTimeToTicks(FILETIME ft)
23 {
24 Ticks t;
25 t = ((Ticks)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
26 t = (t * TICKS_PER_SECOND) / HNS_PER_SEC;
27 return t;
28 }
29
30 void
31 getProcessTimes(Ticks *user, Ticks *elapsed)
32 {
33 *user = getProcessCPUTime();
34 *elapsed = getProcessElapsedTime();
35 }
36
37 Ticks
38 getProcessCPUTime(void)
39 {
40 FILETIME creationTime, exitTime, userTime, kernelTime = {0,0};
41
42 if (!GetProcessTimes(GetCurrentProcess(), &creationTime,
43 &exitTime, &kernelTime, &userTime)) {
44 return 0;
45 }
46
47 return fileTimeToTicks(userTime);
48 }
49
50 // getProcessElapsedTime relies on QueryPerformanceFrequency
51 // which should be available on any Windows computer thay you
52 // would want to run Haskell on. Satnam Singh, 5 July 2010.
53
54 Ticks
55 getProcessElapsedTime(void)
56 {
57 // frequency represents the number of ticks per second
58 // used by the QueryPerformanceFrequency implementaiton
59 // and is represented by a 64-bit union type initially set to 0
60 // and updated just once (hence use of static).
61 static LARGE_INTEGER frequency = {.QuadPart = 0} ;
62
63 // system_time is a 64-bit union type used to represent the
64 // tick count returned by QueryPerformanceCounter
65 LARGE_INTEGER system_time ;
66
67 // If this is the first time we are calling getProcessElapsedTime
68 // then record the ticks per second used by QueryPerformanceCounter
69 if (frequency.QuadPart == 0) {
70 QueryPerformanceFrequency(&frequency);
71 }
72
73 // Get the tick count.
74 QueryPerformanceCounter(&system_time) ;
75
76 // Return the tick count as a millisecond value.
77 // Using double to compute the intermediate value, because a 64-bit
78 // int would overflow when multiplied by TICKS_PER_SECOND in about 81 days.
79 return (Ticks)((TICKS_PER_SECOND * (double)system_time.QuadPart) / (double)frequency.QuadPart) ;
80 }
81
82 Ticks
83 getThreadCPUTime(void)
84 {
85 FILETIME creationTime, exitTime, userTime, kernelTime = {0,0};
86
87 if (!GetThreadTimes(GetCurrentThread(), &creationTime,
88 &exitTime, &kernelTime, &userTime)) {
89 return 0;
90 }
91
92 return fileTimeToTicks(userTime);
93 }
94
95 void
96 getUnixEpochTime(StgWord64 *sec, StgWord32 *nsec)
97 {
98 /* Windows has a bunch of time APIs but none that directly give
99 us unix epoch time, so we have to do a little dance. */
100
101 SYSTEMTIME systime;
102 FILETIME filetime;
103 ULARGE_INTEGER unixtime;
104
105 /* Windows SYSTEMTIME is a big struct with fields for
106 year, month, day, hour, minute, second, millisecond. */
107 GetSystemTime(&systime);
108 /* Windows FILETIME timestamps use an epoch-based time,
109 using a 64bit unsigned word. The time is measured in
110 units of 100 nanoseconds since an epoch of 1601. */
111 SystemTimeToFileTime(&systime, &filetime);
112
113 /* FILETIME isn't directly a 64bit word, but a struct with
114 a pair of 32bit words, so we have to convert via a
115 ULARGE_INTEGER struct which is a handy union type */
116 unixtime.LowPart = filetime.dwLowDateTime;
117 unixtime.HighPart = filetime.dwHighDateTime;
118
119 /* We have to do an epoch conversion, since FILETIME uses 1601
120 while we want unix epoch of 1970. In case you were wondering,
121 there were 11,644,473,600 seconds between 1601 and 1970, then
122 multiply by 10^7 for units of 100 nanoseconds. */
123 unixtime.QuadPart = unixtime.QuadPart - 116444736000000000ull;
124
125 /* For the seconds part we use integer division by 10^7 */
126 *sec = unixtime.QuadPart / 10000000ull;
127
128 /* The remainder from integer division by 10^7 gives us
129 the sub-second component in units of 100 nanoseconds.
130 So for nanoseconds we just multiply by 100.
131 Note that nanoseconds always fits in a 32bit word */
132 *nsec = ((unsigned long)(unixtime.QuadPart % 10000000ull)) * 100ul;
133 }
134
135 nat
136 getPageFaults(void)
137 {
138 /* ToDo (on NT): better, get this via the performance data
139 that's stored in the registry. */
140 return 0;
141 }