blob: a8460c6867955522499c05e6ed465e3d14123c74 [file] [log] [blame]
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00001#include "Python.h"
Victor Stinner09225b72012-02-07 23:41:01 +01002#ifdef MS_WINDOWS
3#include <windows.h>
4#endif
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +00005
Victor Stinnerae586492014-09-02 23:18:25 +02006#if defined(__APPLE__)
7#include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */
8#endif
9
10#ifdef MS_WINDOWS
11static OSVERSIONINFOEX winver;
12#endif
13
Victor Stinner00111242014-08-29 16:31:59 +020014static int
15pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000016{
Victor Stinner09225b72012-02-07 23:41:01 +010017#ifdef MS_WINDOWS
18 FILETIME system_time;
19 ULARGE_INTEGER large;
Victor Stinner4195b5c2012-02-08 23:03:19 +010020 ULONGLONG microseconds;
Victor Stinner09225b72012-02-07 23:41:01 +010021
Victor Stinner00111242014-08-29 16:31:59 +020022 assert(info == NULL || raise);
23
Victor Stinner09225b72012-02-07 23:41:01 +010024 GetSystemTimeAsFileTime(&system_time);
25 large.u.LowPart = system_time.dwLowDateTime;
26 large.u.HighPart = system_time.dwHighDateTime;
Victor Stinner4195b5c2012-02-08 23:03:19 +010027 /* 11,644,473,600,000,000: number of microseconds between
Victor Stinner09225b72012-02-07 23:41:01 +010028 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
29 days). */
Victor Stinner4195b5c2012-02-08 23:03:19 +010030 microseconds = large.QuadPart / 10 - 11644473600000000;
31 tp->tv_sec = microseconds / 1000000;
32 tp->tv_usec = microseconds % 1000000;
Victor Stinnerec895392012-04-29 02:41:27 +020033 if (info) {
34 DWORD timeAdjustment, timeIncrement;
Victor Stinner00111242014-08-29 16:31:59 +020035 BOOL isTimeAdjustmentDisabled, ok;
Victor Stinnerec895392012-04-29 02:41:27 +020036
37 info->implementation = "GetSystemTimeAsFileTime()";
Benjamin Peterson49a69e42012-05-01 09:38:34 -040038 info->monotonic = 0;
Victor Stinner00111242014-08-29 16:31:59 +020039 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
40 &isTimeAdjustmentDisabled);
41 if (!ok) {
42 PyErr_SetFromWindowsErr(0);
43 return -1;
44 }
Victor Stinnerec895392012-04-29 02:41:27 +020045 info->resolution = timeIncrement * 1e-7;
Victor Stinner2b89fdf2012-06-12 22:46:37 +020046 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020047 }
Victor Stinner09225b72012-02-07 23:41:01 +010048
Victor Stinner00111242014-08-29 16:31:59 +020049#else /* MS_WINDOWS */
Victor Stinnerec895392012-04-29 02:41:27 +020050 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020051#ifdef HAVE_CLOCK_GETTIME
52 struct timespec ts;
53#endif
Victor Stinner7efb8332014-08-29 15:41:08 +020054
Victor Stinner00111242014-08-29 16:31:59 +020055 assert(info == NULL || raise);
56
Victor Stinner7efb8332014-08-29 15:41:08 +020057#ifdef HAVE_CLOCK_GETTIME
Victor Stinner00111242014-08-29 16:31:59 +020058 err = clock_gettime(CLOCK_REALTIME, &ts);
59 if (err) {
60 if (raise)
61 PyErr_SetFromErrno(PyExc_OSError);
62 return -1;
Victor Stinner7efb8332014-08-29 15:41:08 +020063 }
Victor Stinner00111242014-08-29 16:31:59 +020064 tp->tv_sec = ts.tv_sec;
65 tp->tv_usec = ts.tv_nsec / 1000;
66
67 if (info) {
68 struct timespec res;
69 info->implementation = "clock_gettime(CLOCK_REALTIME)";
70 info->monotonic = 0;
71 info->adjustable = 1;
72 if (clock_getres(CLOCK_REALTIME, &res) == 0)
73 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
74 else
75 info->resolution = 1e-9;
76 }
Victor Stinner00111242014-08-29 16:31:59 +020077#else /* HAVE_CLOCK_GETTIME */
Victor Stinner7efb8332014-08-29 15:41:08 +020078
79 /* test gettimeofday() */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000080#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020081 err = gettimeofday(tp);
82#else
83 err = gettimeofday(tp, (struct timezone *)NULL);
84#endif
Victor Stinner00111242014-08-29 16:31:59 +020085 if (err) {
86 if (raise)
87 PyErr_SetFromErrno(PyExc_OSError);
88 return -1;
Victor Stinnerec895392012-04-29 02:41:27 +020089 }
Victor Stinner00111242014-08-29 16:31:59 +020090
91 if (info) {
92 info->implementation = "gettimeofday()";
93 info->resolution = 1e-6;
94 info->monotonic = 0;
95 info->adjustable = 1;
96 }
Victor Stinner00111242014-08-29 16:31:59 +020097#endif /* !HAVE_CLOCK_GETTIME */
98#endif /* !MS_WINDOWS */
Victor Stinner9bb758c2014-09-02 23:01:40 +020099 assert(0 <= tp->tv_usec && tp->tv_usec < 1000 * 1000);
100 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000101}
102
Victor Stinnerec895392012-04-29 02:41:27 +0200103void
104_PyTime_gettimeofday(_PyTime_timeval *tp)
105{
Victor Stinner00111242014-08-29 16:31:59 +0200106 if (pygettimeofday(tp, NULL, 0) < 0) {
107 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
108 assert(0);
109 tp->tv_sec = 0;
110 tp->tv_usec = 0;
111 }
Victor Stinnerec895392012-04-29 02:41:27 +0200112}
113
Victor Stinner00111242014-08-29 16:31:59 +0200114int
Victor Stinnerec895392012-04-29 02:41:27 +0200115_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
116{
Victor Stinner00111242014-08-29 16:31:59 +0200117 return pygettimeofday(tp, info, 1);
Victor Stinnerec895392012-04-29 02:41:27 +0200118}
119
Victor Stinnerae586492014-09-02 23:18:25 +0200120static int
121pymonotonic(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
122{
123#ifdef Py_DEBUG
Victor Stinner5789cfb2014-09-03 09:43:48 +0200124 static _PyTime_timeval last = {0, -1};
Victor Stinnerae586492014-09-02 23:18:25 +0200125#endif
126#if defined(MS_WINDOWS)
127 static ULONGLONG (*GetTickCount64) (void) = NULL;
128 static ULONGLONG (CALLBACK *Py_GetTickCount64)(void);
129 static int has_gettickcount64 = -1;
130 ULONGLONG result;
131
132 assert(info == NULL || raise);
133
134 if (has_gettickcount64 == -1) {
135 /* GetTickCount64() was added to Windows Vista */
136 has_gettickcount64 = (winver.dwMajorVersion >= 6);
137 if (has_gettickcount64) {
138 HINSTANCE hKernel32;
139 hKernel32 = GetModuleHandleW(L"KERNEL32");
140 *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32,
141 "GetTickCount64");
142 assert(Py_GetTickCount64 != NULL);
143 }
144 }
145
146 if (has_gettickcount64) {
147 result = Py_GetTickCount64();
148 }
149 else {
150 static DWORD last_ticks = 0;
151 static DWORD n_overflow = 0;
152 DWORD ticks;
153
154 ticks = GetTickCount();
155 if (ticks < last_ticks)
156 n_overflow++;
157 last_ticks = ticks;
158
159 result = (ULONGLONG)n_overflow << 32;
160 result += ticks;
161 }
162
163 tp->tv_sec = result / 1000;
164 tp->tv_usec = (result % 1000) * 1000;
165
166 if (info) {
167 DWORD timeAdjustment, timeIncrement;
168 BOOL isTimeAdjustmentDisabled, ok;
169 if (has_gettickcount64)
170 info->implementation = "GetTickCount64()";
171 else
172 info->implementation = "GetTickCount()";
173 info->monotonic = 1;
174 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
175 &isTimeAdjustmentDisabled);
176 if (!ok) {
177 PyErr_SetFromWindowsErr(0);
178 return -1;
179 }
180 info->resolution = timeIncrement * 1e-7;
181 info->adjustable = 0;
182 }
183
184#elif defined(__APPLE__)
185 static mach_timebase_info_data_t timebase;
186 uint64_t time;
187
188 if (timebase.denom == 0) {
189 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
190 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
191 (void)mach_timebase_info(&timebase);
192 }
193
194 time = mach_absolute_time();
195
196 /* nanoseconds => microseconds */
197 time /= 1000;
198 /* apply timebase factor */
199 time *= timebase.numer;
200 time /= timebase.denom;
201 tp->tv_sec = time / (1000 * 1000);
202 tp->tv_usec = time % (1000 * 1000);
203
204 if (info) {
205 info->implementation = "mach_absolute_time()";
206 info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
207 info->monotonic = 1;
208 info->adjustable = 0;
209 }
210
211#else
212 struct timespec ts;
213#ifdef CLOCK_HIGHRES
214 const clockid_t clk_id = CLOCK_HIGHRES;
215 const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
216#else
217 const clockid_t clk_id = CLOCK_MONOTONIC;
218 const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
219#endif
220
221 assert(info == NULL || raise);
222
223 if (clock_gettime(clk_id, &ts) != 0) {
224 if (raise) {
225 PyErr_SetFromErrno(PyExc_OSError);
226 return -1;
227 }
228 tp->tv_sec = 0;
229 tp->tv_usec = 0;
230 return -1;
231 }
232
233 if (info) {
234 struct timespec res;
235 info->monotonic = 1;
236 info->implementation = implementation;
237 info->adjustable = 0;
238 if (clock_getres(clk_id, &res) != 0) {
239 PyErr_SetFromErrno(PyExc_OSError);
240 return -1;
241 }
242 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
243 }
244 tp->tv_sec = ts.tv_sec;
245 tp->tv_usec = ts.tv_nsec / 1000;
246#endif
247 assert(0 <= tp->tv_usec && tp->tv_usec < 1000 * 1000);
248#ifdef Py_DEBUG
249 /* monotonic clock cannot go backward */
Victor Stinner5789cfb2014-09-03 09:43:48 +0200250 assert(last.tv_usec == -1
251 || tp->tv_sec > last.tv_sec
Victor Stinnerae586492014-09-02 23:18:25 +0200252 || (tp->tv_sec == last.tv_sec && tp->tv_usec >= last.tv_usec));
253 last = *tp;
254#endif
255 return 0;
256}
257
258void
259_PyTime_monotonic(_PyTime_timeval *tp)
260{
261 if (pymonotonic(tp, NULL, 0) < 0) {
262 /* cannot happen, _PyTime_Init() checks that pymonotonic() works */
263 assert(0);
264 tp->tv_sec = 0;
265 tp->tv_usec = 0;
266 }
267}
268
269int
270_PyTime_monotonic_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
271{
272 return pymonotonic(tp, info, 1);
273}
274
Victor Stinner5d272cc2012-03-13 13:35:55 +0100275static void
276error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100277{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100278 PyErr_SetString(PyExc_OverflowError,
279 "timestamp out of range for platform time_t");
280}
281
Larry Hastings76ad59b2012-05-03 00:30:07 -0700282time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100283_PyLong_AsTime_t(PyObject *obj)
284{
285#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
286 PY_LONG_LONG val;
287 val = PyLong_AsLongLong(obj);
288#else
289 long val;
290 assert(sizeof(time_t) <= sizeof(long));
291 val = PyLong_AsLong(obj);
292#endif
293 if (val == -1 && PyErr_Occurred()) {
294 if (PyErr_ExceptionMatches(PyExc_OverflowError))
295 error_time_t_overflow();
296 return -1;
297 }
298 return (time_t)val;
299}
300
Larry Hastings6fe20b32012-04-19 15:07:49 -0700301PyObject *
302_PyLong_FromTime_t(time_t t)
303{
304#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
305 return PyLong_FromLongLong((PY_LONG_LONG)t);
306#else
307 assert(sizeof(time_t) <= sizeof(long));
308 return PyLong_FromLong((long)t);
309#endif
310}
311
Victor Stinner5d272cc2012-03-13 13:35:55 +0100312static int
313_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100314 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100315{
316 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100317 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100318 double d, intpart, err;
319 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
320 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100321
322 d = PyFloat_AsDouble(obj);
323 floatpart = modf(d, &intpart);
324 if (floatpart < 0) {
325 floatpart = 1.0 + floatpart;
326 intpart -= 1.0;
327 }
328
Victor Stinner3c1b3792014-02-17 00:02:43 +0100329 floatpart *= denominator;
330 if (round == _PyTime_ROUND_UP) {
331 if (intpart >= 0) {
332 floatpart = ceil(floatpart);
333 if (floatpart >= denominator) {
334 floatpart = 0.0;
335 intpart += 1.0;
336 }
337 }
338 else {
339 floatpart = floor(floatpart);
340 }
341 }
342
Victor Stinner643cd682012-03-02 22:54:03 +0100343 *sec = (time_t)intpart;
344 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100345 if (err <= -1.0 || err >= 1.0) {
346 error_time_t_overflow();
347 return -1;
348 }
Victor Stinner643cd682012-03-02 22:54:03 +0100349
Victor Stinner5d272cc2012-03-13 13:35:55 +0100350 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100351 return 0;
352 }
353 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100354 *sec = _PyLong_AsTime_t(obj);
355 if (*sec == (time_t)-1 && PyErr_Occurred())
356 return -1;
357 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100358 return 0;
359 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100360}
Victor Stinner643cd682012-03-02 22:54:03 +0100361
Victor Stinner5d272cc2012-03-13 13:35:55 +0100362int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100363_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100364{
365 if (PyFloat_Check(obj)) {
366 double d, intpart, err;
367
Victor Stinner5d272cc2012-03-13 13:35:55 +0100368 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100369 if (round == _PyTime_ROUND_UP) {
370 if (d >= 0)
371 d = ceil(d);
372 else
373 d = floor(d);
374 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100375 (void)modf(d, &intpart);
376
377 *sec = (time_t)intpart;
378 err = intpart - (double)*sec;
379 if (err <= -1.0 || err >= 1.0) {
380 error_time_t_overflow();
381 return -1;
382 }
383 return 0;
384 }
385 else {
386 *sec = _PyLong_AsTime_t(obj);
387 if (*sec == (time_t)-1 && PyErr_Occurred())
388 return -1;
389 return 0;
390 }
391}
392
393int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100394_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
395 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100396{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100397 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100398}
399
400int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100401_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
402 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100403{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100404 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100405}
406
Victor Stinner00111242014-08-29 16:31:59 +0200407int
408_PyTime_Init(void)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000409{
Victor Stinner00111242014-08-29 16:31:59 +0200410 _PyTime_timeval tv;
Victor Stinnerae586492014-09-02 23:18:25 +0200411
412#ifdef MS_WINDOWS
413 winver.dwOSVersionInfoSize = sizeof(winver);
414 if (!GetVersionEx((OSVERSIONINFO*)&winver)) {
415 PyErr_SetFromWindowsErr(0);
416 return -1;
417 }
418#endif
419
Victor Stinner00111242014-08-29 16:31:59 +0200420 /* ensure that the system clock works */
421 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
422 return -1;
Victor Stinnerae586492014-09-02 23:18:25 +0200423
424 /* ensure that the operating system provides a monotonic clock */
425 if (_PyTime_monotonic_info(&tv, NULL) < 0)
426 return -1;
Victor Stinner00111242014-08-29 16:31:59 +0200427 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000428}