blob: cdaa22ec669a0f3fc9c81ab50cc5db9aa9b3f034 [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 Stinner00111242014-08-29 16:31:59 +020010static int
11pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000012{
Victor Stinner09225b72012-02-07 23:41:01 +010013#ifdef MS_WINDOWS
14 FILETIME system_time;
15 ULARGE_INTEGER large;
Victor Stinner4195b5c2012-02-08 23:03:19 +010016 ULONGLONG microseconds;
Victor Stinner09225b72012-02-07 23:41:01 +010017
Victor Stinner00111242014-08-29 16:31:59 +020018 assert(info == NULL || raise);
19
Victor Stinner09225b72012-02-07 23:41:01 +010020 GetSystemTimeAsFileTime(&system_time);
21 large.u.LowPart = system_time.dwLowDateTime;
22 large.u.HighPart = system_time.dwHighDateTime;
Victor Stinner4195b5c2012-02-08 23:03:19 +010023 /* 11,644,473,600,000,000: number of microseconds between
Victor Stinner09225b72012-02-07 23:41:01 +010024 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
25 days). */
Victor Stinner4195b5c2012-02-08 23:03:19 +010026 microseconds = large.QuadPart / 10 - 11644473600000000;
27 tp->tv_sec = microseconds / 1000000;
28 tp->tv_usec = microseconds % 1000000;
Victor Stinnerec895392012-04-29 02:41:27 +020029 if (info) {
30 DWORD timeAdjustment, timeIncrement;
Victor Stinner00111242014-08-29 16:31:59 +020031 BOOL isTimeAdjustmentDisabled, ok;
Victor Stinnerec895392012-04-29 02:41:27 +020032
33 info->implementation = "GetSystemTimeAsFileTime()";
Benjamin Peterson49a69e42012-05-01 09:38:34 -040034 info->monotonic = 0;
Victor Stinner00111242014-08-29 16:31:59 +020035 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
36 &isTimeAdjustmentDisabled);
37 if (!ok) {
38 PyErr_SetFromWindowsErr(0);
39 return -1;
40 }
Victor Stinnerec895392012-04-29 02:41:27 +020041 info->resolution = timeIncrement * 1e-7;
Victor Stinner2b89fdf2012-06-12 22:46:37 +020042 info->adjustable = 1;
Victor Stinnerec895392012-04-29 02:41:27 +020043 }
Victor Stinner09225b72012-02-07 23:41:01 +010044
Victor Stinner00111242014-08-29 16:31:59 +020045#else /* MS_WINDOWS */
Victor Stinnerec895392012-04-29 02:41:27 +020046 int err;
Victor Stinner7efb8332014-08-29 15:41:08 +020047#ifdef HAVE_CLOCK_GETTIME
48 struct timespec ts;
49#endif
Victor Stinner7efb8332014-08-29 15:41:08 +020050
Victor Stinner00111242014-08-29 16:31:59 +020051 assert(info == NULL || raise);
52
Victor Stinner7efb8332014-08-29 15:41:08 +020053#ifdef HAVE_CLOCK_GETTIME
Victor Stinner00111242014-08-29 16:31:59 +020054 err = clock_gettime(CLOCK_REALTIME, &ts);
55 if (err) {
56 if (raise)
57 PyErr_SetFromErrno(PyExc_OSError);
58 return -1;
Victor Stinner7efb8332014-08-29 15:41:08 +020059 }
Victor Stinner00111242014-08-29 16:31:59 +020060 tp->tv_sec = ts.tv_sec;
61 tp->tv_usec = ts.tv_nsec / 1000;
62
63 if (info) {
64 struct timespec res;
65 info->implementation = "clock_gettime(CLOCK_REALTIME)";
66 info->monotonic = 0;
67 info->adjustable = 1;
68 if (clock_getres(CLOCK_REALTIME, &res) == 0)
69 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
70 else
71 info->resolution = 1e-9;
72 }
Victor Stinner00111242014-08-29 16:31:59 +020073#else /* HAVE_CLOCK_GETTIME */
Victor Stinner7efb8332014-08-29 15:41:08 +020074
75 /* test gettimeofday() */
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000076#ifdef GETTIMEOFDAY_NO_TZ
Victor Stinnerec895392012-04-29 02:41:27 +020077 err = gettimeofday(tp);
78#else
79 err = gettimeofday(tp, (struct timezone *)NULL);
80#endif
Victor Stinner00111242014-08-29 16:31:59 +020081 if (err) {
82 if (raise)
83 PyErr_SetFromErrno(PyExc_OSError);
84 return -1;
Victor Stinnerec895392012-04-29 02:41:27 +020085 }
Victor Stinner00111242014-08-29 16:31:59 +020086
87 if (info) {
88 info->implementation = "gettimeofday()";
89 info->resolution = 1e-6;
90 info->monotonic = 0;
91 info->adjustable = 1;
92 }
Victor Stinner00111242014-08-29 16:31:59 +020093#endif /* !HAVE_CLOCK_GETTIME */
94#endif /* !MS_WINDOWS */
Victor Stinner9bb758c2014-09-02 23:01:40 +020095 assert(0 <= tp->tv_usec && tp->tv_usec < 1000 * 1000);
96 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +000097}
98
Victor Stinnerec895392012-04-29 02:41:27 +020099void
100_PyTime_gettimeofday(_PyTime_timeval *tp)
101{
Victor Stinner00111242014-08-29 16:31:59 +0200102 if (pygettimeofday(tp, NULL, 0) < 0) {
103 /* cannot happen, _PyTime_Init() checks that pygettimeofday() works */
104 assert(0);
105 tp->tv_sec = 0;
106 tp->tv_usec = 0;
107 }
Victor Stinnerec895392012-04-29 02:41:27 +0200108}
109
Victor Stinner00111242014-08-29 16:31:59 +0200110int
Victor Stinnerec895392012-04-29 02:41:27 +0200111_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
112{
Victor Stinner00111242014-08-29 16:31:59 +0200113 return pygettimeofday(tp, info, 1);
Victor Stinnerec895392012-04-29 02:41:27 +0200114}
115
Victor Stinnerae586492014-09-02 23:18:25 +0200116static int
117pymonotonic(_PyTime_timeval *tp, _Py_clock_info_t *info, int raise)
118{
119#ifdef Py_DEBUG
Victor Stinner5789cfb2014-09-03 09:43:48 +0200120 static _PyTime_timeval last = {0, -1};
Victor Stinnerae586492014-09-02 23:18:25 +0200121#endif
122#if defined(MS_WINDOWS)
Victor Stinnerae586492014-09-02 23:18:25 +0200123 ULONGLONG result;
124
125 assert(info == NULL || raise);
126
Steve Dower3e96f322015-03-02 08:01:10 -0800127 result = GetTickCount64();
Victor Stinnerae586492014-09-02 23:18:25 +0200128
129 tp->tv_sec = result / 1000;
130 tp->tv_usec = (result % 1000) * 1000;
131
132 if (info) {
133 DWORD timeAdjustment, timeIncrement;
134 BOOL isTimeAdjustmentDisabled, ok;
Steve Dower3e96f322015-03-02 08:01:10 -0800135 info->implementation = "GetTickCount64()";
Victor Stinnerae586492014-09-02 23:18:25 +0200136 info->monotonic = 1;
137 ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
138 &isTimeAdjustmentDisabled);
139 if (!ok) {
140 PyErr_SetFromWindowsErr(0);
141 return -1;
142 }
143 info->resolution = timeIncrement * 1e-7;
144 info->adjustable = 0;
145 }
146
147#elif defined(__APPLE__)
148 static mach_timebase_info_data_t timebase;
149 uint64_t time;
150
151 if (timebase.denom == 0) {
152 /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
153 fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
154 (void)mach_timebase_info(&timebase);
155 }
156
157 time = mach_absolute_time();
158
159 /* nanoseconds => microseconds */
160 time /= 1000;
161 /* apply timebase factor */
162 time *= timebase.numer;
163 time /= timebase.denom;
164 tp->tv_sec = time / (1000 * 1000);
165 tp->tv_usec = time % (1000 * 1000);
166
167 if (info) {
168 info->implementation = "mach_absolute_time()";
169 info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
170 info->monotonic = 1;
171 info->adjustable = 0;
172 }
173
174#else
175 struct timespec ts;
176#ifdef CLOCK_HIGHRES
177 const clockid_t clk_id = CLOCK_HIGHRES;
178 const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
179#else
180 const clockid_t clk_id = CLOCK_MONOTONIC;
181 const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
182#endif
183
184 assert(info == NULL || raise);
185
186 if (clock_gettime(clk_id, &ts) != 0) {
187 if (raise) {
188 PyErr_SetFromErrno(PyExc_OSError);
189 return -1;
190 }
191 tp->tv_sec = 0;
192 tp->tv_usec = 0;
193 return -1;
194 }
195
196 if (info) {
197 struct timespec res;
198 info->monotonic = 1;
199 info->implementation = implementation;
200 info->adjustable = 0;
201 if (clock_getres(clk_id, &res) != 0) {
202 PyErr_SetFromErrno(PyExc_OSError);
203 return -1;
204 }
205 info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
206 }
207 tp->tv_sec = ts.tv_sec;
208 tp->tv_usec = ts.tv_nsec / 1000;
209#endif
210 assert(0 <= tp->tv_usec && tp->tv_usec < 1000 * 1000);
211#ifdef Py_DEBUG
212 /* monotonic clock cannot go backward */
Victor Stinner5789cfb2014-09-03 09:43:48 +0200213 assert(last.tv_usec == -1
214 || tp->tv_sec > last.tv_sec
Victor Stinnerae586492014-09-02 23:18:25 +0200215 || (tp->tv_sec == last.tv_sec && tp->tv_usec >= last.tv_usec));
216 last = *tp;
217#endif
218 return 0;
219}
220
221void
222_PyTime_monotonic(_PyTime_timeval *tp)
223{
224 if (pymonotonic(tp, NULL, 0) < 0) {
225 /* cannot happen, _PyTime_Init() checks that pymonotonic() works */
226 assert(0);
227 tp->tv_sec = 0;
228 tp->tv_usec = 0;
229 }
230}
231
232int
233_PyTime_monotonic_info(_PyTime_timeval *tp, _Py_clock_info_t *info)
234{
235 return pymonotonic(tp, info, 1);
236}
237
Victor Stinner5d272cc2012-03-13 13:35:55 +0100238static void
239error_time_t_overflow(void)
Victor Stinner643cd682012-03-02 22:54:03 +0100240{
Victor Stinner5d272cc2012-03-13 13:35:55 +0100241 PyErr_SetString(PyExc_OverflowError,
242 "timestamp out of range for platform time_t");
243}
244
Larry Hastings76ad59b2012-05-03 00:30:07 -0700245time_t
Victor Stinner5d272cc2012-03-13 13:35:55 +0100246_PyLong_AsTime_t(PyObject *obj)
247{
248#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
249 PY_LONG_LONG val;
250 val = PyLong_AsLongLong(obj);
251#else
252 long val;
253 assert(sizeof(time_t) <= sizeof(long));
254 val = PyLong_AsLong(obj);
255#endif
256 if (val == -1 && PyErr_Occurred()) {
257 if (PyErr_ExceptionMatches(PyExc_OverflowError))
258 error_time_t_overflow();
259 return -1;
260 }
261 return (time_t)val;
262}
263
Larry Hastings6fe20b32012-04-19 15:07:49 -0700264PyObject *
265_PyLong_FromTime_t(time_t t)
266{
267#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
268 return PyLong_FromLongLong((PY_LONG_LONG)t);
269#else
270 assert(sizeof(time_t) <= sizeof(long));
271 return PyLong_FromLong((long)t);
272#endif
273}
274
Victor Stinner5d272cc2012-03-13 13:35:55 +0100275static int
276_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
Victor Stinner3c1b3792014-02-17 00:02:43 +0100277 double denominator, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100278{
279 assert(denominator <= LONG_MAX);
Victor Stinner643cd682012-03-02 22:54:03 +0100280 if (PyFloat_Check(obj)) {
Victor Stinnerbd273c12012-03-13 19:12:23 +0100281 double d, intpart, err;
282 /* volatile avoids unsafe optimization on float enabled by gcc -O3 */
283 volatile double floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100284
285 d = PyFloat_AsDouble(obj);
286 floatpart = modf(d, &intpart);
287 if (floatpart < 0) {
288 floatpart = 1.0 + floatpart;
289 intpart -= 1.0;
290 }
291
Victor Stinner3c1b3792014-02-17 00:02:43 +0100292 floatpart *= denominator;
293 if (round == _PyTime_ROUND_UP) {
294 if (intpart >= 0) {
295 floatpart = ceil(floatpart);
296 if (floatpart >= denominator) {
297 floatpart = 0.0;
298 intpart += 1.0;
299 }
300 }
301 else {
302 floatpart = floor(floatpart);
303 }
304 }
305
Victor Stinner643cd682012-03-02 22:54:03 +0100306 *sec = (time_t)intpart;
307 err = intpart - (double)*sec;
Victor Stinner5d272cc2012-03-13 13:35:55 +0100308 if (err <= -1.0 || err >= 1.0) {
309 error_time_t_overflow();
310 return -1;
311 }
Victor Stinner643cd682012-03-02 22:54:03 +0100312
Victor Stinner5d272cc2012-03-13 13:35:55 +0100313 *numerator = (long)floatpart;
Victor Stinner643cd682012-03-02 22:54:03 +0100314 return 0;
315 }
316 else {
Victor Stinner5d272cc2012-03-13 13:35:55 +0100317 *sec = _PyLong_AsTime_t(obj);
318 if (*sec == (time_t)-1 && PyErr_Occurred())
319 return -1;
320 *numerator = 0;
Victor Stinner643cd682012-03-02 22:54:03 +0100321 return 0;
322 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100323}
Victor Stinner643cd682012-03-02 22:54:03 +0100324
Victor Stinner5d272cc2012-03-13 13:35:55 +0100325int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100326_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100327{
328 if (PyFloat_Check(obj)) {
329 double d, intpart, err;
330
Victor Stinner5d272cc2012-03-13 13:35:55 +0100331 d = PyFloat_AsDouble(obj);
Victor Stinner3c1b3792014-02-17 00:02:43 +0100332 if (round == _PyTime_ROUND_UP) {
333 if (d >= 0)
334 d = ceil(d);
335 else
336 d = floor(d);
337 }
Victor Stinner5d272cc2012-03-13 13:35:55 +0100338 (void)modf(d, &intpart);
339
340 *sec = (time_t)intpart;
341 err = intpart - (double)*sec;
342 if (err <= -1.0 || err >= 1.0) {
343 error_time_t_overflow();
344 return -1;
345 }
346 return 0;
347 }
348 else {
349 *sec = _PyLong_AsTime_t(obj);
350 if (*sec == (time_t)-1 && PyErr_Occurred())
351 return -1;
352 return 0;
353 }
354}
355
356int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100357_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
358 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100359{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100360 return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
Victor Stinner5d272cc2012-03-13 13:35:55 +0100361}
362
363int
Victor Stinner3c1b3792014-02-17 00:02:43 +0100364_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
365 _PyTime_round_t round)
Victor Stinner5d272cc2012-03-13 13:35:55 +0100366{
Victor Stinner3c1b3792014-02-17 00:02:43 +0100367 return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
Victor Stinner643cd682012-03-02 22:54:03 +0100368}
369
Victor Stinner00111242014-08-29 16:31:59 +0200370int
371_PyTime_Init(void)
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000372{
Victor Stinner00111242014-08-29 16:31:59 +0200373 _PyTime_timeval tv;
Victor Stinnerae586492014-09-02 23:18:25 +0200374
Victor Stinner00111242014-08-29 16:31:59 +0200375 /* ensure that the system clock works */
376 if (_PyTime_gettimeofday_info(&tv, NULL) < 0)
377 return -1;
Victor Stinnerae586492014-09-02 23:18:25 +0200378
379 /* ensure that the operating system provides a monotonic clock */
380 if (_PyTime_monotonic_info(&tv, NULL) < 0)
381 return -1;
Victor Stinner00111242014-08-29 16:31:59 +0200382 return 0;
Alexander Belopolsky6fc4ade2010-08-05 17:34:27 +0000383}