blob: 578569d4dd1bdb04e2495b02048add0354bdc986 [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
Victor Stinner580ef132015-03-20 01:55:04 +010010#define SEC_TO_MS 1000
11#define MS_TO_US 1000
12#define US_TO_NS 1000
13
14#define SEC_TO_US (SEC_TO_MS * MS_TO_US)
15
Victor Stinner00111242014-08-29 16:31:59 +020016static int
17pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000018{
Victor Stinner09225b72012-02-07 23:41:01 +010019#ifdef MS_WINDOWS
20 FILETIME system_time;
21 ULARGE_INTEGER large;
Victor Stinner4195b5c2012-02-08 23:03:19 +010022 ULONGLONG microseconds;
Victor Stinner09225b72012-02-07 23:41:01 +010023
Victor Stinner00111242014-08-29 16:31:59 +020024 assert(info == NULL || raise);
25
Victor Stinner09225b72012-02-07 23:41:01 +010026 GetSystemTimeAsFileTime(&system_time);
27 large.u.LowPart = system_time.dwLowDateTime;
28 large.u.HighPart = system_time.dwHighDateTime;
Victor Stinner4195b5c2012-02-08 23:03:19 +010029 /* 11,644,473,600,000,000: number of microseconds between
Victor Stinner09225b72012-02-07 23:41:01 +010030 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
31 days). */
Victor Stinner4195b5c2012-02-08 23:03:19 +010032 microseconds = large.QuadPart / 10 - 11644473600000000;
Victor Stinner580ef132015-03-20 01:55:04 +010033 tp->tv_sec = microseconds / SEC_TO_US;
34 tp->tv_usec = microseconds % SEC_TO_US;
Victor Stinnerec895392012-04-29 02:41:27 +020035 if (info) {
36 DWORD timeAdjustment, timeIncrement;
Victor Stinner00111242014-08-29 16:31:59 +020037 BOOL isTimeAdjustmentDisabled, ok;
Victor Stinnerec895392012-04-29 02:41:27 +020038
39 info->implementation = "GetSystemTimeAsFileTime()";
Benjamin Peterson49a69e42012-05-01 09:38:34 -040040 info->monotonic = 0;
Victor Stinner00111242014-08-29 16:31:59 +020041 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
42 &isTimeAdjustmentDisabled);
43 if (!ok) {
44 PyErr_SetFromWindowsErr(0);
45 return -1;
46 }
Victor Stinnerec895392012-04-29 02:41:27 +020047 info->resolution = timeIncrement * 1e-7;
Victor Stinner2b89fdf2012-06-12 22:46:37 +020048 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020049 }
Victor Stinner09225b72012-02-07 23:41:01 +010050
Victor Stinner00111242014-08-29 16:31:59 +020051#else /* MS_WINDOWS */
Victor Stinnerec895392012-04-29 02:41:27 +020052 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020053#ifdef HAVE_CLOCK_GETTIME
54 struct timespec ts;
55#endif
Victor Stinner7efb8332014-08-29 15:41:08 +020056
Victor Stinner00111242014-08-29 16:31:59 +020057 assert(info == NULL || raise);
58
Victor Stinner7efb8332014-08-29 15:41:08 +020059#ifdef HAVE_CLOCK_GETTIME
Victor Stinner00111242014-08-29 16:31:59 +020060 err = clock_gettime(CLOCK_REALTIME, &ts);
61 if (err) {
62 if (raise)
63 PyErr_SetFromErrno(PyExc_OSError);
64 return -1;
Victor Stinner7efb8332014-08-29 15:41:08 +020065 }
Victor Stinner00111242014-08-29 16:31:59 +020066 tp->tv_sec = ts.tv_sec;
Victor Stinner580ef132015-03-20 01:55:04 +010067 tp->tv_usec = ts.tv_nsec / US_TO_NS;
Victor Stinner00111242014-08-29 16:31:59 +020068
69 if (info) {
70 struct timespec res;
71 info->implementation = "clock_gettime(CLOCK_REALTIME)";
72 info->monotonic = 0;
73 info->adjustable = 1;
74 if (clock_getres(CLOCK_REALTIME, &res) == 0)
75 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
76 else
77 info->resolution = 1e-9;
78 }
Victor Stinner00111242014-08-29 16:31:59 +020079#else /* HAVE_CLOCK_GETTIME */
Victor Stinner7efb8332014-08-29 15:41:08 +020080
81 /* test gettimeofday() */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000082#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020083 err = gettimeofday(tp);
84#else
85 err = gettimeofday(tp, (struct timezone *)NULL);
86#endif
Victor Stinner00111242014-08-29 16:31:59 +020087 if (err) {
88 if (raise)
89 PyErr_SetFromErrno(PyExc_OSError);
90 return -1;
Victor Stinnerec895392012-04-29 02:41:27 +020091 }
Victor Stinner00111242014-08-29 16:31:59 +020092
93 if (info) {
94 info->implementation = "gettimeofday()";
95 info->resolution = 1e-6;
96 info->monotonic = 0;
97 info->adjustable = 1;
98 }
Victor Stinner00111242014-08-29 16:31:59 +020099#endif /* !HAVE_CLOCK_GETTIME */
100#endif /* !MS_WINDOWS */
Victor Stinner580ef132015-03-20 01:55:04 +0100101 assert(0 <= tp->tv_usec && tp->tv_usec < SEC_TO_US);
Victor Stinner9bb758c2014-09-02 23:01:40 +0200102 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000103}
104
Victor Stinnerec895392012-04-29 02:41:27 +0200105void
106_PyTime_gettimeofday(_PyTime_timeval *tp)
107{
Victor Stinner00111242014-08-29 16:31:59 +0200108 if (pygettimeofday(tp, NULL, 0) < 0) {
109 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
110 assert(0);
111 tp->tv_sec = 0;
112 tp->tv_usec = 0;
113 }
Victor Stinnerec895392012-04-29 02:41:27 +0200114}
115
Victor Stinner00111242014-08-29 16:31:59 +0200116int
Victor Stinnerec895392012-04-29 02:41:27 +0200117_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
118{
Victor Stinner00111242014-08-29 16:31:59 +0200119 return pygettimeofday(tp, info, 1);
Victor Stinnerec895392012-04-29 02:41:27 +0200120}
121
Victor Stinnerae586492014-09-02 23:18:25 +0200122static int
123pymonotonic(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
124{
125#ifdef Py_DEBUG
Victor Stinner5789cfb2014-09-03 09:43:48 +0200126 static _PyTime_timeval last = {0, -1};
Victor Stinnerae586492014-09-02 23:18:25 +0200127#endif
128#if defined(MS_WINDOWS)
Victor Stinnerae586492014-09-02 23:18:25 +0200129 ULONGLONG result;
130
131 assert(info == NULL || raise);
132
Steve Dower3e96f322015-03-02 08:01:10 -0800133 result = GetTickCount64();
Victor Stinnerae586492014-09-02 23:18:25 +0200134
Victor Stinner580ef132015-03-20 01:55:04 +0100135 tp->tv_sec = result / SEC_TO_MS;
136 tp->tv_usec = (result % SEC_TO_MS) * MS_TO_US;
Victor Stinnerae586492014-09-02 23:18:25 +0200137
138 if (info) {
139 DWORD timeAdjustment, timeIncrement;
140 BOOL isTimeAdjustmentDisabled, ok;
Steve Dower3e96f322015-03-02 08:01:10 -0800141 info->implementation = "GetTickCount64()";
Victor Stinnerae586492014-09-02 23:18:25 +0200142 info->monotonic = 1;
143 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
144 &isTimeAdjustmentDisabled);
145 if (!ok) {
146 PyErr_SetFromWindowsErr(0);
147 return -1;
148 }
149 info->resolution = timeIncrement * 1e-7;
150 info->adjustable = 0;
151 }
152
153#elif defined(__APPLE__)
154 static mach_timebase_info_data_t timebase;
155 uint64_t time;
156
157 if (timebase.denom == 0) {
158 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
159 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
160 (void)mach_timebase_info(&timebase);
161 }
162
163 time = mach_absolute_time();
164
165 /* nanoseconds => microseconds */
Victor Stinner580ef132015-03-20 01:55:04 +0100166 time /= US_TO_NS;
Victor Stinnerae586492014-09-02 23:18:25 +0200167 /* apply timebase factor */
168 time *= timebase.numer;
169 time /= timebase.denom;
Victor Stinner580ef132015-03-20 01:55:04 +0100170 tp->tv_sec = time / SEC_TO_US;
171 tp->tv_usec = time % SEC_TO_US;
Victor Stinnerae586492014-09-02 23:18:25 +0200172
173 if (info) {
174 info->implementation = "mach_absolute_time()";
175 info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
176 info->monotonic = 1;
177 info->adjustable = 0;
178 }
179
180#else
181 struct timespec ts;
182#ifdef CLOCK_HIGHRES
183 const clockid_t clk_id = CLOCK_HIGHRES;
184 const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
185#else
186 const clockid_t clk_id = CLOCK_MONOTONIC;
187 const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
188#endif
189
190 assert(info == NULL || raise);
191
192 if (clock_gettime(clk_id, &ts) != 0) {
193 if (raise) {
194 PyErr_SetFromErrno(PyExc_OSError);
195 return -1;
196 }
197 tp->tv_sec = 0;
198 tp->tv_usec = 0;
199 return -1;
200 }
201
202 if (info) {
203 struct timespec res;
204 info->monotonic = 1;
205 info->implementation = implementation;
206 info->adjustable = 0;
207 if (clock_getres(clk_id, &res) != 0) {
208 PyErr_SetFromErrno(PyExc_OSError);
209 return -1;
210 }
211 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
212 }
213 tp->tv_sec = ts.tv_sec;
Victor Stinner580ef132015-03-20 01:55:04 +0100214 tp->tv_usec = ts.tv_nsec / US_TO_NS;
Victor Stinnerae586492014-09-02 23:18:25 +0200215#endif
Victor Stinner580ef132015-03-20 01:55:04 +0100216 assert(0 <= tp->tv_usec && tp->tv_usec < SEC_TO_US);
Victor Stinnerae586492014-09-02 23:18:25 +0200217#ifdef Py_DEBUG
218 /* monotonic clock cannot go backward */
Victor Stinner5789cfb2014-09-03 09:43:48 +0200219 assert(last.tv_usec == -1
220 || tp->tv_sec > last.tv_sec
Victor Stinnerae586492014-09-02 23:18:25 +0200221 || (tp->tv_sec == last.tv_sec && tp->tv_usec >= last.tv_usec));
222 last = *tp;
223#endif
224 return 0;
225}
226
227void
228_PyTime_monotonic(_PyTime_timeval *tp)
229{
230 if (pymonotonic(tp, NULL, 0) < 0) {
231 /* cannot happen, _PyTime_Init() checks that pymonotonic() works */
232 assert(0);
233 tp->tv_sec = 0;
234 tp->tv_usec = 0;
235 }
236}
237
238int
239_PyTime_monotonic_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
240{
241 return pymonotonic(tp, info, 1);
242}
243
Victor Stinner5d272cc2012-03-13 13:35:55 +0100244static void
245error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100246{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100247 PyErr_SetString(PyExc_OverflowError,
248 "timestamp out of range for platform time_t");
249}
250
Larry Hastings76ad59b2012-05-03 00:30:07 -0700251time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100252_PyLong_AsTime_t(PyObject *obj)
253{
254#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
255 PY_LONG_LONG val;
256 val = PyLong_AsLongLong(obj);
257#else
258 long val;
259 assert(sizeof(time_t) <= sizeof(long));
260 val = PyLong_AsLong(obj);
261#endif
262 if (val == -1 && PyErr_Occurred()) {
263 if (PyErr_ExceptionMatches(PyExc_OverflowError))
264 error_time_t_overflow();
265 return -1;
266 }
267 return (time_t)val;
268}
269
Larry Hastings6fe20b32012-04-19 15:07:49 -0700270PyObject *
271_PyLong_FromTime_t(time_t t)
272{
273#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
274 return PyLong_FromLongLong((PY_LONG_LONG)t);
275#else
276 assert(sizeof(time_t) <= sizeof(long));
277 return PyLong_FromLong((long)t);
278#endif
279}
280
Victor Stinner5d272cc2012-03-13 13:35:55 +0100281static int
282_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100283 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100284{
285 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100286 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100287 double d, intpart, err;
288 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
289 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100290
291 d = PyFloat_AsDouble(obj);
292 floatpart = modf(d, &intpart);
293 if (floatpart < 0) {
294 floatpart = 1.0 + floatpart;
295 intpart -= 1.0;
296 }
297
Victor Stinner3c1b3792014-02-17 00:02:43 +0100298 floatpart *= denominator;
299 if (round == _PyTime_ROUND_UP) {
300 if (intpart >= 0) {
301 floatpart = ceil(floatpart);
302 if (floatpart >= denominator) {
303 floatpart = 0.0;
304 intpart += 1.0;
305 }
306 }
307 else {
308 floatpart = floor(floatpart);
309 }
310 }
311
Victor Stinner643cd682012-03-02 22:54:03 +0100312 *sec = (time_t)intpart;
313 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100314 if (err <= -1.0 || err >= 1.0) {
315 error_time_t_overflow();
316 return -1;
317 }
Victor Stinner643cd682012-03-02 22:54:03 +0100318
Victor Stinner5d272cc2012-03-13 13:35:55 +0100319 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100320 return 0;
321 }
322 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100323 *sec = _PyLong_AsTime_t(obj);
324 if (*sec == (time_t)-1 && PyErr_Occurred())
325 return -1;
326 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100327 return 0;
328 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100329}
Victor Stinner643cd682012-03-02 22:54:03 +0100330
Victor Stinner5d272cc2012-03-13 13:35:55 +0100331int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100332_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100333{
334 if (PyFloat_Check(obj)) {
335 double d, intpart, err;
336
Victor Stinner5d272cc2012-03-13 13:35:55 +0100337 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100338 if (round == _PyTime_ROUND_UP) {
339 if (d >= 0)
340 d = ceil(d);
341 else
342 d = floor(d);
343 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100344 (void)modf(d, &intpart);
345
346 *sec = (time_t)intpart;
347 err = intpart - (double)*sec;
348 if (err <= -1.0 || err >= 1.0) {
349 error_time_t_overflow();
350 return -1;
351 }
352 return 0;
353 }
354 else {
355 *sec = _PyLong_AsTime_t(obj);
356 if (*sec == (time_t)-1 && PyErr_Occurred())
357 return -1;
358 return 0;
359 }
360}
361
362int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100363_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
364 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100365{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100366 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100367}
368
369int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100370_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
371 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100372{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100373 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100374}
375
Victor Stinner9a8089b2015-03-20 01:42:20 +0100376void
377_PyTime_AddDouble(_PyTime_timeval *tv, double interval, _PyTime_round_t round)
378{
379 _PyTime_timeval tv2;
380 double frac;
381
382 frac = fmod(interval, 1.0);
383 interval = floor(interval);
384 tv2.tv_sec = (long)interval;
385 tv2.tv_usec = (long)(frac*1e6);
386
387 tv->tv_sec += tv2.tv_sec;
388 tv->tv_usec += tv2.tv_usec;
Victor Stinner580ef132015-03-20 01:55:04 +0100389 tv->tv_sec += (time_t)(tv->tv_usec / SEC_TO_US);
390 tv->tv_usec %= SEC_TO_US;
Victor Stinner9a8089b2015-03-20 01:42:20 +0100391}
392
Victor Stinner00111242014-08-29 16:31:59 +0200393int
394_PyTime_Init(void)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000395{
Victor Stinner00111242014-08-29 16:31:59 +0200396 _PyTime_timeval tv;
Victor Stinnerae586492014-09-02 23:18:25 +0200397
Victor Stinner00111242014-08-29 16:31:59 +0200398 /* ensure that the system clock works */
399 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
400 return -1;
Victor Stinnerae586492014-09-02 23:18:25 +0200401
402 /* ensure that the operating system provides a monotonic clock */
403 if (_PyTime_monotonic_info(&tv, NULL) < 0)
404 return -1;
Victor Stinner00111242014-08-29 16:31:59 +0200405 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000406}