Revert "rts: add Emacs 'Local Variables' to every .c file"
[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 /* Convert FILETIMEs into secs */
19
20 static INLINE_ME Time
21 fileTimeToRtsTime(FILETIME ft)
22 {
23 Time t;
24 t = ((Time)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
25 t = NSToTime(t * 100);
26 /* FILETIMES are in units of 100ns */
27 return t;
28 }
29
30 void
31 getProcessTimes(Time *user, Time *elapsed)
32 {
33 *user = getProcessCPUTime();
34 *elapsed = getProcessElapsedTime();
35 }
36
37 Time
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 fileTimeToRtsTime(userTime);
48 }
49
50 // Number of ticks per second used by the QueryPerformanceFrequency
51 // implementaiton, represented by a 64-bit union type.
52 static LARGE_INTEGER qpc_frequency = {.QuadPart = 0};
53
54 // Initialize qpc_frequency. This function should be called before any call to
55 // getMonotonicNSec. If QPC is not supported on this system, qpc_frequency is
56 // set to 0.
57 void initializeTimer()
58 {
59 BOOL qpc_supported = QueryPerformanceFrequency(&qpc_frequency);
60 if (!qpc_supported)
61 {
62 qpc_frequency.QuadPart = 0;
63 }
64 }
65
66 HsWord64
67 getMonotonicNSec()
68 {
69 if (qpc_frequency.QuadPart)
70 {
71 // system_time is a 64-bit union type used to represent the
72 // tick count returned by QueryPerformanceCounter
73 LARGE_INTEGER system_time;
74
75 // get the tick count.
76 QueryPerformanceCounter(&system_time);
77
78 // compute elapsed seconds as double
79 double secs = (double)system_time.QuadPart /
80 (double)qpc_frequency.QuadPart;
81
82 // return elapsed time in nanoseconds
83 return (HsWord64)(secs * 1e9);
84 }
85 else // fallback to GetTickCount
86 {
87 // NOTE: GetTickCount is a 32-bit millisecond value, so it wraps around
88 // every 49 days.
89 DWORD count = GetTickCount();
90
91 // getTickCount is in milliseconds, so multiply it by 1000000 to get
92 // nanoseconds.
93 return (HsWord64)count * 1000000;
94 }
95 }
96
97 Time
98 getProcessElapsedTime(void)
99 {
100 return NSToTime(getMonotonicNSec());
101 }
102
103 Time
104 getThreadCPUTime(void)
105 {
106 FILETIME creationTime, exitTime, userTime, kernelTime = {0,0};
107
108 if (!GetThreadTimes(GetCurrentThread(), &creationTime,
109 &exitTime, &kernelTime, &userTime)) {
110 return 0;
111 }
112
113 return fileTimeToRtsTime(userTime);
114 }
115
116 void
117 getUnixEpochTime(StgWord64 *sec, StgWord32 *nsec)
118 {
119 /* Windows has a bunch of time APIs but none that directly give
120 us unix epoch time, so we have to do a little dance. */
121
122 SYSTEMTIME systime;
123 FILETIME filetime;
124 ULARGE_INTEGER unixtime;
125
126 /* Windows SYSTEMTIME is a big struct with fields for
127 year, month, day, hour, minute, second, millisecond. */
128 GetSystemTime(&systime);
129 /* Windows FILETIME timestamps use an epoch-based time,
130 using a 64bit unsigned word. The time is measured in
131 units of 100 nanoseconds since an epoch of 1601. */
132 SystemTimeToFileTime(&systime, &filetime);
133
134 /* FILETIME isn't directly a 64bit word, but a struct with
135 a pair of 32bit words, so we have to convert via a
136 ULARGE_INTEGER struct which is a handy union type */
137 unixtime.LowPart = filetime.dwLowDateTime;
138 unixtime.HighPart = filetime.dwHighDateTime;
139
140 /* We have to do an epoch conversion, since FILETIME uses 1601
141 while we want unix epoch of 1970. In case you were wondering,
142 there were 11,644,473,600 seconds between 1601 and 1970, then
143 multiply by 10^7 for units of 100 nanoseconds. */
144 unixtime.QuadPart = unixtime.QuadPart - 116444736000000000ull;
145
146 /* For the seconds part we use integer division by 10^7 */
147 *sec = unixtime.QuadPart / 10000000ull;
148
149 /* The remainder from integer division by 10^7 gives us
150 the sub-second component in units of 100 nanoseconds.
151 So for nanoseconds we just multiply by 100.
152 Note that nanoseconds always fits in a 32bit word */
153 *nsec = ((unsigned long)(unixtime.QuadPart % 10000000ull)) * 100ul;
154 }
155
156 W_
157 getPageFaults(void)
158 {
159 /* ToDo (on NT): better, get this via the performance data
160 that's stored in the registry. */
161 return 0;
162 }