2 #include <realtimeapiset.h>
9 system_qpc_tickspersec ()
14 QueryPerformanceFrequency (&qpf
);
18 static inline LONGLONG
19 system_tickcount_period ()
21 ULONG coarsest
= 0, finest
, actual
;
25 /* The actual resolution of the OS timer is a system-wide setting which
26 can be changed any time, by any process. The only fixed value we
27 can rely on is the coarsest value. */
28 NtQueryTimerResolution (&coarsest
, &finest
, &actual
);
37 InterlockedExchange64 (&period
, system_tickcount_period ());
41 clk_realtime_t::init ()
44 InterlockedExchange64 (&ticks_per_sec
, system_qpc_tickspersec ());
48 clk_monotonic_t::init ()
51 InterlockedExchange64 (&ticks_per_sec
, system_qpc_tickspersec ());
55 clk_realtime_coarse_t::now (clockid_t clockid
, struct timespec
*ts
)
59 GetSystemTimeAsFileTime ((LPFILETIME
) &now
);
60 /* Add conversion factor for UNIX vs. Windows base time */
61 now
.QuadPart
-= FACTOR
;
62 ts
->tv_sec
= now
.QuadPart
/ NS100PERSEC
;
63 ts
->tv_nsec
= (now
.QuadPart
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
68 clk_realtime_t::now (clockid_t clockid
, struct timespec
*ts
)
72 GetSystemTimePreciseAsFileTime ((LPFILETIME
) &now
);
73 /* Add conversion factor for UNIX vs. Windows base time */
74 now
.QuadPart
-= FACTOR
;
75 ts
->tv_sec
= now
.QuadPart
/ NS100PERSEC
;
76 ts
->tv_nsec
= (now
.QuadPart
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
81 clk_process_t::now (clockid_t clockid
, struct timespec
*ts
)
83 pid_t pid
= CLOCKID_TO_PID (clockid
);
85 KERNEL_USER_TIMES kut
;
92 if (!p
|| !p
->exists ())
98 hProcess
= OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION
, 0,
100 NtQueryInformationProcess (hProcess
, ProcessTimes
,
101 &kut
, sizeof kut
, NULL
);
103 x
= kut
.KernelTime
.QuadPart
+ kut
.UserTime
.QuadPart
;
104 ts
->tv_sec
= x
/ NS100PERSEC
;
105 ts
->tv_nsec
= (x
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
106 CloseHandle (hProcess
);
111 clk_thread_t::now (clockid_t clockid
, struct timespec
*ts
)
113 long thr_id
= CLOCKID_TO_THREADID (clockid
);
115 KERNEL_USER_TIMES kut
;
119 thr_id
= pthread::self ()->getsequence_np ();
121 hThread
= OpenThread (THREAD_QUERY_LIMITED_INFORMATION
, 0, thr_id
);
128 NtQueryInformationThread (hThread
, ThreadTimes
,
129 &kut
, sizeof kut
, NULL
);
131 x
= kut
.KernelTime
.QuadPart
+ kut
.UserTime
.QuadPart
;
132 ts
->tv_sec
= x
/ NS100PERSEC
;
133 ts
->tv_nsec
= (x
% NS100PERSEC
) * (NSPERSEC
/NS100PERSEC
);
134 CloseHandle (hThread
);
139 clk_monotonic_t::now (clockid_t clockid
, struct timespec
*ts
)
141 if (wincap
.has_precise_interrupt_time ())
143 /* Suspend time not taken into account, as on Linux */
146 QueryUnbiasedInterruptTimePrecise (&now
);
147 ts
->tv_sec
= now
/ NS100PERSEC
;
149 ts
->tv_nsec
= now
* (NSPERSEC
/NS100PERSEC
);
153 /* https://stackoverflow.com/questions/24330496. Skip rounding since
154 its almost always wrong when working with timestamps */
162 bias
= SharedUserData
.InterruptTimeBias
;
163 QueryPerformanceCounter(&now
);
165 while (bias
!= SharedUserData
.InterruptTimeBias
);
166 /* Convert perf counter to timespec */
167 ts
->tv_sec
= now
.QuadPart
/ ticks_per_sec
;
168 now
.QuadPart
%= ticks_per_sec
;
169 ts
->tv_nsec
= (now
.QuadPart
* NSPERSEC
) / ticks_per_sec
;
170 /* Convert bias to timespec */
171 bts
.tv_sec
= bias
/ NS100PERSEC
;
173 bts
.tv_nsec
= bias
* (NSPERSEC
/NS100PERSEC
);
174 /* Subtract bias from perf */
181 clk_monotonic_coarse_t::now (clockid_t clockid
, struct timespec
*ts
)
183 /* Suspend time not taken into account, as on Linux */
186 QueryUnbiasedInterruptTime (&now
);
187 ts
->tv_sec
= now
/ NS100PERSEC
;
189 ts
->tv_nsec
= now
* (NSPERSEC
/NS100PERSEC
);
194 clk_boottime_t::now (clockid_t clockid
, struct timespec
*ts
)
196 /* Suspend time taken into account, as on Linux */
197 if (wincap
.has_precise_interrupt_time ())
201 QueryInterruptTimePrecise (&now
);
202 ts
->tv_sec
= now
/ NS100PERSEC
;
204 ts
->tv_nsec
= now
* (NSPERSEC
/NS100PERSEC
);
211 QueryPerformanceCounter (&now
);
212 ts
->tv_sec
= now
.QuadPart
/ ticks_per_sec
;
213 now
.QuadPart
%= ticks_per_sec
;
214 ts
->tv_nsec
= (now
.QuadPart
* NSPERSEC
) / ticks_per_sec
;
220 clk_t::resolution (struct timespec
*ts
)
224 ts
->tv_nsec
= period
* (NSPERSEC
/NS100PERSEC
);
228 clk_realtime_t::resolution (struct timespec
*ts
)
232 ts
->tv_nsec
= NSPERSEC
/ ticks_per_sec
;
236 clk_monotonic_t::resolution (struct timespec
*ts
)
240 ts
->tv_nsec
= NSPERSEC
/ ticks_per_sec
;
243 static clk_realtime_coarse_t clk_realtime_coarse
;
244 static clk_realtime_t clk_realtime
;
245 static clk_process_t clk_process
;
246 static clk_thread_t clk_thread
;
247 static clk_monotonic_t clk_monotonic
;
248 static clk_monotonic_t clk_monotonic_raw
; /* same as clk_monotonic */
249 static clk_monotonic_coarse_t clk_monotonic_coarse
;
250 static clk_boottime_t clk_boottime
;
251 static clk_realtime_t clk_realtime_alarm
; /* same as clk_realtime */
252 static clk_boottime_t clk_boottime_alarm
; /* same as clk_boottime_t */
254 clk_t
*cyg_clock
[MAX_CLOCKS
] =
256 &clk_realtime_coarse
,
262 &clk_monotonic_coarse
,
269 get_clock (clockid_t clk_id
)
271 extern clk_t
*cyg_clock
[MAX_CLOCKS
];
272 clockid_t clockid
= CLOCKID (clk_id
);
273 if (clk_id
>= MAX_CLOCKS
274 && clockid
!= CLOCK_PROCESS_CPUTIME_ID
275 && clockid
!= CLOCK_THREAD_CPUTIME_ID
)
277 return cyg_clock
[clockid
];