/src/Python-3.8.3/Python/pytime.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "Python.h" |
2 | | #ifdef MS_WINDOWS |
3 | | #include <windows.h> |
4 | | #endif |
5 | | |
6 | | #if defined(__APPLE__) |
7 | | #include <mach/mach_time.h> /* mach_absolute_time(), mach_timebase_info() */ |
8 | | #endif |
9 | | |
10 | | #define _PyTime_check_mul_overflow(a, b) \ |
11 | 57 | (assert(b > 0), \ |
12 | 57 | (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \ |
13 | 57 | || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a)) |
14 | | |
15 | | /* To millisecond (10^-3) */ |
16 | 962 | #define SEC_TO_MS 1000 |
17 | | |
18 | | /* To microseconds (10^-6) */ |
19 | 962 | #define MS_TO_US 1000 |
20 | 0 | #define SEC_TO_US (SEC_TO_MS * MS_TO_US) |
21 | | |
22 | | /* To nanoseconds (10^-9) */ |
23 | 962 | #define US_TO_NS 1000 |
24 | 962 | #define MS_TO_NS (MS_TO_US * US_TO_NS) |
25 | 962 | #define SEC_TO_NS (SEC_TO_MS * MS_TO_NS) |
26 | | |
27 | | /* Conversion from nanoseconds */ |
28 | 0 | #define NS_TO_MS (1000 * 1000) |
29 | 859 | #define NS_TO_US (1000) |
30 | | |
31 | | static void |
32 | | error_time_t_overflow(void) |
33 | 0 | { |
34 | 0 | PyErr_SetString(PyExc_OverflowError, |
35 | 0 | "timestamp out of range for platform time_t"); |
36 | 0 | } |
37 | | |
38 | | static void |
39 | | _PyTime_overflow(void) |
40 | 0 | { |
41 | 0 | PyErr_SetString(PyExc_OverflowError, |
42 | 0 | "timestamp too large to convert to C _PyTime_t"); |
43 | 0 | } |
44 | | |
45 | | |
46 | | _PyTime_t |
47 | | _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) |
48 | 0 | { |
49 | 0 | _PyTime_t intpart, remaining; |
50 | | /* Compute (ticks * mul / div) in two parts to prevent integer overflow: |
51 | | compute integer part, and then the remaining part. |
52 | | |
53 | | (ticks * mul) / div == (ticks / div) * mul + (ticks % div) * mul / div |
54 | | |
55 | | The caller must ensure that "(div - 1) * mul" cannot overflow. */ |
56 | 0 | intpart = ticks / div; |
57 | 0 | ticks %= div; |
58 | 0 | remaining = ticks * mul; |
59 | 0 | remaining /= div; |
60 | 0 | return intpart * mul + remaining; |
61 | 0 | } |
62 | | |
63 | | |
64 | | time_t |
65 | | _PyLong_AsTime_t(PyObject *obj) |
66 | 0 | { |
67 | 0 | #if SIZEOF_TIME_T == SIZEOF_LONG_LONG |
68 | 0 | long long val; |
69 | 0 | val = PyLong_AsLongLong(obj); |
70 | | #else |
71 | | long val; |
72 | | Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long)); |
73 | | val = PyLong_AsLong(obj); |
74 | | #endif |
75 | 0 | if (val == -1 && PyErr_Occurred()) { |
76 | 0 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
77 | 0 | error_time_t_overflow(); |
78 | 0 | } |
79 | 0 | return -1; |
80 | 0 | } |
81 | 0 | return (time_t)val; |
82 | 0 | } |
83 | | |
84 | | PyObject * |
85 | | _PyLong_FromTime_t(time_t t) |
86 | 2.56k | { |
87 | 2.56k | #if SIZEOF_TIME_T == SIZEOF_LONG_LONG |
88 | 2.56k | return PyLong_FromLongLong((long long)t); |
89 | | #else |
90 | | Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long)); |
91 | | return PyLong_FromLong((long)t); |
92 | | #endif |
93 | 2.56k | } |
94 | | |
95 | | /* Round to nearest with ties going to nearest even integer |
96 | | (_PyTime_ROUND_HALF_EVEN) */ |
97 | | static double |
98 | | _PyTime_RoundHalfEven(double x) |
99 | 0 | { |
100 | 0 | double rounded = round(x); |
101 | 0 | if (fabs(x-rounded) == 0.5) { |
102 | | /* halfway case: round to even */ |
103 | 0 | rounded = 2.0*round(x/2.0); |
104 | 0 | } |
105 | 0 | return rounded; |
106 | 0 | } |
107 | | |
108 | | static double |
109 | | _PyTime_Round(double x, _PyTime_round_t round) |
110 | 0 | { |
111 | | /* volatile avoids optimization changing how numbers are rounded */ |
112 | 0 | volatile double d; |
113 | |
|
114 | 0 | d = x; |
115 | 0 | if (round == _PyTime_ROUND_HALF_EVEN) { |
116 | 0 | d = _PyTime_RoundHalfEven(d); |
117 | 0 | } |
118 | 0 | else if (round == _PyTime_ROUND_CEILING) { |
119 | 0 | d = ceil(d); |
120 | 0 | } |
121 | 0 | else if (round == _PyTime_ROUND_FLOOR) { |
122 | 0 | d = floor(d); |
123 | 0 | } |
124 | 0 | else { |
125 | 0 | assert(round == _PyTime_ROUND_UP); |
126 | 0 | d = (d >= 0.0) ? ceil(d) : floor(d); |
127 | 0 | } |
128 | 0 | return d; |
129 | 0 | } |
130 | | |
131 | | static int |
132 | | _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, |
133 | | long idenominator, _PyTime_round_t round) |
134 | 0 | { |
135 | 0 | double denominator = (double)idenominator; |
136 | 0 | double intpart; |
137 | | /* volatile avoids optimization changing how numbers are rounded */ |
138 | 0 | volatile double floatpart; |
139 | |
|
140 | 0 | floatpart = modf(d, &intpart); |
141 | |
|
142 | 0 | floatpart *= denominator; |
143 | 0 | floatpart = _PyTime_Round(floatpart, round); |
144 | 0 | if (floatpart >= denominator) { |
145 | 0 | floatpart -= denominator; |
146 | 0 | intpart += 1.0; |
147 | 0 | } |
148 | 0 | else if (floatpart < 0) { |
149 | 0 | floatpart += denominator; |
150 | 0 | intpart -= 1.0; |
151 | 0 | } |
152 | 0 | assert(0.0 <= floatpart && floatpart < denominator); |
153 | |
|
154 | 0 | if (!_Py_InIntegralTypeRange(time_t, intpart)) { |
155 | 0 | error_time_t_overflow(); |
156 | 0 | return -1; |
157 | 0 | } |
158 | 0 | *sec = (time_t)intpart; |
159 | 0 | *numerator = (long)floatpart; |
160 | 0 | assert(0 <= *numerator && *numerator < idenominator); |
161 | 0 | return 0; |
162 | 0 | } |
163 | | |
164 | | static int |
165 | | _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, |
166 | | long denominator, _PyTime_round_t round) |
167 | 0 | { |
168 | 0 | assert(denominator >= 1); |
169 | |
|
170 | 0 | if (PyFloat_Check(obj)) { |
171 | 0 | double d = PyFloat_AsDouble(obj); |
172 | 0 | if (Py_IS_NAN(d)) { |
173 | 0 | *numerator = 0; |
174 | 0 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
175 | 0 | return -1; |
176 | 0 | } |
177 | 0 | return _PyTime_DoubleToDenominator(d, sec, numerator, |
178 | 0 | denominator, round); |
179 | 0 | } |
180 | 0 | else { |
181 | 0 | *sec = _PyLong_AsTime_t(obj); |
182 | 0 | *numerator = 0; |
183 | 0 | if (*sec == (time_t)-1 && PyErr_Occurred()) { |
184 | 0 | return -1; |
185 | 0 | } |
186 | 0 | return 0; |
187 | 0 | } |
188 | 0 | } |
189 | | |
190 | | int |
191 | | _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) |
192 | 0 | { |
193 | 0 | if (PyFloat_Check(obj)) { |
194 | 0 | double intpart; |
195 | | /* volatile avoids optimization changing how numbers are rounded */ |
196 | 0 | volatile double d; |
197 | |
|
198 | 0 | d = PyFloat_AsDouble(obj); |
199 | 0 | if (Py_IS_NAN(d)) { |
200 | 0 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
201 | 0 | return -1; |
202 | 0 | } |
203 | | |
204 | 0 | d = _PyTime_Round(d, round); |
205 | 0 | (void)modf(d, &intpart); |
206 | |
|
207 | 0 | if (!_Py_InIntegralTypeRange(time_t, intpart)) { |
208 | 0 | error_time_t_overflow(); |
209 | 0 | return -1; |
210 | 0 | } |
211 | 0 | *sec = (time_t)intpart; |
212 | 0 | return 0; |
213 | 0 | } |
214 | 0 | else { |
215 | 0 | *sec = _PyLong_AsTime_t(obj); |
216 | 0 | if (*sec == (time_t)-1 && PyErr_Occurred()) { |
217 | 0 | return -1; |
218 | 0 | } |
219 | 0 | return 0; |
220 | 0 | } |
221 | 0 | } |
222 | | |
223 | | int |
224 | | _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, |
225 | | _PyTime_round_t round) |
226 | 0 | { |
227 | 0 | return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round); |
228 | 0 | } |
229 | | |
230 | | int |
231 | | _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, |
232 | | _PyTime_round_t round) |
233 | 0 | { |
234 | 0 | return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round); |
235 | 0 | } |
236 | | |
237 | | _PyTime_t |
238 | | _PyTime_FromSeconds(int seconds) |
239 | 876 | { |
240 | 876 | _PyTime_t t; |
241 | | /* ensure that integer overflow cannot happen, int type should have 32 |
242 | | bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30 |
243 | | bits). */ |
244 | 876 | Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS); |
245 | 876 | Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS); |
246 | | |
247 | 876 | t = (_PyTime_t)seconds; |
248 | 876 | assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS) |
249 | 876 | || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS)); |
250 | 876 | t *= SEC_TO_NS; |
251 | 876 | return t; |
252 | 876 | } |
253 | | |
254 | | _PyTime_t |
255 | | _PyTime_FromNanoseconds(_PyTime_t ns) |
256 | 0 | { |
257 | | /* _PyTime_t already uses nanosecond resolution, no conversion needed */ |
258 | 0 | return ns; |
259 | 0 | } |
260 | | |
261 | | int |
262 | | _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) |
263 | 0 | { |
264 | 0 | long long nsec; |
265 | 0 | _PyTime_t t; |
266 | |
|
267 | 0 | if (!PyLong_Check(obj)) { |
268 | 0 | PyErr_Format(PyExc_TypeError, "expect int, got %s", |
269 | 0 | Py_TYPE(obj)->tp_name); |
270 | 0 | return -1; |
271 | 0 | } |
272 | | |
273 | 0 | Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t)); |
274 | 0 | nsec = PyLong_AsLongLong(obj); |
275 | 0 | if (nsec == -1 && PyErr_Occurred()) { |
276 | 0 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
277 | 0 | _PyTime_overflow(); |
278 | 0 | } |
279 | 0 | return -1; |
280 | 0 | } |
281 | | |
282 | | /* _PyTime_t already uses nanosecond resolution, no conversion needed */ |
283 | 0 | t = (_PyTime_t)nsec; |
284 | 0 | *tp = t; |
285 | 0 | return 0; |
286 | 0 | } |
287 | | |
288 | | #ifdef HAVE_CLOCK_GETTIME |
289 | | static int |
290 | | pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise) |
291 | 57 | { |
292 | 57 | _PyTime_t t, nsec; |
293 | 57 | int res = 0; |
294 | | |
295 | 57 | Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t)); |
296 | 57 | t = (_PyTime_t)ts->tv_sec; |
297 | | |
298 | 57 | if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { |
299 | 0 | if (raise) { |
300 | 0 | _PyTime_overflow(); |
301 | 0 | } |
302 | 0 | res = -1; |
303 | 0 | t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; |
304 | 0 | } |
305 | 57 | else { |
306 | 57 | t = t * SEC_TO_NS; |
307 | 57 | } |
308 | | |
309 | 57 | nsec = ts->tv_nsec; |
310 | | /* The following test is written for positive only nsec */ |
311 | 57 | assert(nsec >= 0); |
312 | 57 | if (t > _PyTime_MAX - nsec) { |
313 | 0 | if (raise) { |
314 | 0 | _PyTime_overflow(); |
315 | 0 | } |
316 | 0 | res = -1; |
317 | 0 | t = _PyTime_MAX; |
318 | 0 | } |
319 | 57 | else { |
320 | 57 | t += nsec; |
321 | 57 | } |
322 | | |
323 | 57 | *tp = t; |
324 | 57 | return res; |
325 | 57 | } |
326 | | |
327 | | int |
328 | | _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) |
329 | 0 | { |
330 | 0 | return pytime_fromtimespec(tp, ts, 1); |
331 | 0 | } |
332 | | #endif |
333 | | |
334 | | #if !defined(MS_WINDOWS) |
335 | | static int |
336 | | pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) |
337 | 0 | { |
338 | 0 | _PyTime_t t, usec; |
339 | 0 | int res = 0; |
340 | |
|
341 | 0 | Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t)); |
342 | 0 | t = (_PyTime_t)tv->tv_sec; |
343 | |
|
344 | 0 | if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { |
345 | 0 | if (raise) { |
346 | 0 | _PyTime_overflow(); |
347 | 0 | } |
348 | 0 | res = -1; |
349 | 0 | t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; |
350 | 0 | } |
351 | 0 | else { |
352 | 0 | t = t * SEC_TO_NS; |
353 | 0 | } |
354 | |
|
355 | 0 | usec = (_PyTime_t)tv->tv_usec * US_TO_NS; |
356 | | /* The following test is written for positive only usec */ |
357 | 0 | assert(usec >= 0); |
358 | 0 | if (t > _PyTime_MAX - usec) { |
359 | 0 | if (raise) { |
360 | 0 | _PyTime_overflow(); |
361 | 0 | } |
362 | 0 | res = -1; |
363 | 0 | t = _PyTime_MAX; |
364 | 0 | } |
365 | 0 | else { |
366 | 0 | t += usec; |
367 | 0 | } |
368 | |
|
369 | 0 | *tp = t; |
370 | 0 | return res; |
371 | 0 | } |
372 | | |
373 | | int |
374 | | _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv) |
375 | 0 | { |
376 | 0 | return pytime_fromtimeval(tp, tv, 1); |
377 | 0 | } |
378 | | #endif |
379 | | |
380 | | static int |
381 | | _PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round, |
382 | | long unit_to_ns) |
383 | 0 | { |
384 | | /* volatile avoids optimization changing how numbers are rounded */ |
385 | 0 | volatile double d; |
386 | | |
387 | | /* convert to a number of nanoseconds */ |
388 | 0 | d = value; |
389 | 0 | d *= (double)unit_to_ns; |
390 | 0 | d = _PyTime_Round(d, round); |
391 | |
|
392 | 0 | if (!_Py_InIntegralTypeRange(_PyTime_t, d)) { |
393 | 0 | _PyTime_overflow(); |
394 | 0 | return -1; |
395 | 0 | } |
396 | 0 | *t = (_PyTime_t)d; |
397 | 0 | return 0; |
398 | 0 | } |
399 | | |
400 | | static int |
401 | | _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, |
402 | | long unit_to_ns) |
403 | 0 | { |
404 | 0 | if (PyFloat_Check(obj)) { |
405 | 0 | double d; |
406 | 0 | d = PyFloat_AsDouble(obj); |
407 | 0 | if (Py_IS_NAN(d)) { |
408 | 0 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
409 | 0 | return -1; |
410 | 0 | } |
411 | 0 | return _PyTime_FromDouble(t, d, round, unit_to_ns); |
412 | 0 | } |
413 | 0 | else { |
414 | 0 | long long sec; |
415 | 0 | Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t)); |
416 | |
|
417 | 0 | sec = PyLong_AsLongLong(obj); |
418 | 0 | if (sec == -1 && PyErr_Occurred()) { |
419 | 0 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { |
420 | 0 | _PyTime_overflow(); |
421 | 0 | } |
422 | 0 | return -1; |
423 | 0 | } |
424 | | |
425 | 0 | if (_PyTime_check_mul_overflow(sec, unit_to_ns)) { |
426 | 0 | _PyTime_overflow(); |
427 | 0 | return -1; |
428 | 0 | } |
429 | 0 | *t = sec * unit_to_ns; |
430 | 0 | return 0; |
431 | 0 | } |
432 | 0 | } |
433 | | |
434 | | int |
435 | | _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) |
436 | 0 | { |
437 | 0 | return _PyTime_FromObject(t, obj, round, SEC_TO_NS); |
438 | 0 | } |
439 | | |
440 | | int |
441 | | _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) |
442 | 0 | { |
443 | 0 | return _PyTime_FromObject(t, obj, round, MS_TO_NS); |
444 | 0 | } |
445 | | |
446 | | double |
447 | | _PyTime_AsSecondsDouble(_PyTime_t t) |
448 | 29 | { |
449 | | /* volatile avoids optimization changing how numbers are rounded */ |
450 | 29 | volatile double d; |
451 | | |
452 | 29 | if (t % SEC_TO_NS == 0) { |
453 | 0 | _PyTime_t secs; |
454 | | /* Divide using integers to avoid rounding issues on the integer part. |
455 | | 1e-9 cannot be stored exactly in IEEE 64-bit. */ |
456 | 0 | secs = t / SEC_TO_NS; |
457 | 0 | d = (double)secs; |
458 | 0 | } |
459 | 29 | else { |
460 | 29 | d = (double)t; |
461 | 29 | d /= 1e9; |
462 | 29 | } |
463 | 29 | return d; |
464 | 29 | } |
465 | | |
466 | | PyObject * |
467 | | _PyTime_AsNanosecondsObject(_PyTime_t t) |
468 | 0 | { |
469 | 0 | Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t)); |
470 | 0 | return PyLong_FromLongLong((long long)t); |
471 | 0 | } |
472 | | |
473 | | static _PyTime_t |
474 | | _PyTime_Divide(const _PyTime_t t, const _PyTime_t k, |
475 | | const _PyTime_round_t round) |
476 | 859 | { |
477 | 859 | assert(k > 1); |
478 | 859 | if (round == _PyTime_ROUND_HALF_EVEN) { |
479 | 0 | _PyTime_t x, r, abs_r; |
480 | 0 | x = t / k; |
481 | 0 | r = t % k; |
482 | 0 | abs_r = Py_ABS(r); |
483 | 0 | if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) { |
484 | 0 | if (t >= 0) { |
485 | 0 | x++; |
486 | 0 | } |
487 | 0 | else { |
488 | 0 | x--; |
489 | 0 | } |
490 | 0 | } |
491 | 0 | return x; |
492 | 0 | } |
493 | 859 | else if (round == _PyTime_ROUND_CEILING) { |
494 | 859 | if (t >= 0) { |
495 | 1 | return (t + k - 1) / k; |
496 | 1 | } |
497 | 858 | else { |
498 | 858 | return t / k; |
499 | 858 | } |
500 | 859 | } |
501 | 0 | else if (round == _PyTime_ROUND_FLOOR){ |
502 | 0 | if (t >= 0) { |
503 | 0 | return t / k; |
504 | 0 | } |
505 | 0 | else { |
506 | 0 | return (t - (k - 1)) / k; |
507 | 0 | } |
508 | 0 | } |
509 | 0 | else { |
510 | 0 | assert(round == _PyTime_ROUND_UP); |
511 | 0 | if (t >= 0) { |
512 | 0 | return (t + k - 1) / k; |
513 | 0 | } |
514 | 0 | else { |
515 | 0 | return (t - (k - 1)) / k; |
516 | 0 | } |
517 | 0 | } |
518 | 859 | } |
519 | | |
520 | | _PyTime_t |
521 | | _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) |
522 | 0 | { |
523 | 0 | return _PyTime_Divide(t, NS_TO_MS, round); |
524 | 0 | } |
525 | | |
526 | | _PyTime_t |
527 | | _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) |
528 | 859 | { |
529 | 859 | return _PyTime_Divide(t, NS_TO_US, round); |
530 | 859 | } |
531 | | |
532 | | static int |
533 | | _PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us, |
534 | | _PyTime_round_t round) |
535 | 0 | { |
536 | 0 | _PyTime_t secs, ns; |
537 | 0 | int usec; |
538 | 0 | int res = 0; |
539 | |
|
540 | 0 | secs = t / SEC_TO_NS; |
541 | 0 | ns = t % SEC_TO_NS; |
542 | |
|
543 | 0 | usec = (int)_PyTime_Divide(ns, US_TO_NS, round); |
544 | 0 | if (usec < 0) { |
545 | 0 | usec += SEC_TO_US; |
546 | 0 | if (secs != _PyTime_MIN) { |
547 | 0 | secs -= 1; |
548 | 0 | } |
549 | 0 | else { |
550 | 0 | res = -1; |
551 | 0 | } |
552 | 0 | } |
553 | 0 | else if (usec >= SEC_TO_US) { |
554 | 0 | usec -= SEC_TO_US; |
555 | 0 | if (secs != _PyTime_MAX) { |
556 | 0 | secs += 1; |
557 | 0 | } |
558 | 0 | else { |
559 | 0 | res = -1; |
560 | 0 | } |
561 | 0 | } |
562 | 0 | assert(0 <= usec && usec < SEC_TO_US); |
563 | |
|
564 | 0 | *p_secs = secs; |
565 | 0 | *p_us = usec; |
566 | |
|
567 | 0 | return res; |
568 | 0 | } |
569 | | |
570 | | static int |
571 | | _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, |
572 | | _PyTime_round_t round, int raise) |
573 | 0 | { |
574 | 0 | _PyTime_t secs, secs2; |
575 | 0 | int us; |
576 | 0 | int res; |
577 | |
|
578 | 0 | res = _PyTime_AsTimeval_impl(t, &secs, &us, round); |
579 | |
|
580 | | #ifdef MS_WINDOWS |
581 | | tv->tv_sec = (long)secs; |
582 | | #else |
583 | 0 | tv->tv_sec = secs; |
584 | 0 | #endif |
585 | 0 | tv->tv_usec = us; |
586 | |
|
587 | 0 | secs2 = (_PyTime_t)tv->tv_sec; |
588 | 0 | if (res < 0 || secs2 != secs) { |
589 | 0 | if (raise) { |
590 | 0 | error_time_t_overflow(); |
591 | 0 | } |
592 | 0 | return -1; |
593 | 0 | } |
594 | 0 | return 0; |
595 | 0 | } |
596 | | |
597 | | int |
598 | | _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) |
599 | 0 | { |
600 | 0 | return _PyTime_AsTimevalStruct_impl(t, tv, round, 1); |
601 | 0 | } |
602 | | |
603 | | int |
604 | | _PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) |
605 | 0 | { |
606 | 0 | return _PyTime_AsTimevalStruct_impl(t, tv, round, 0); |
607 | 0 | } |
608 | | |
609 | | int |
610 | | _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, |
611 | | _PyTime_round_t round) |
612 | 0 | { |
613 | 0 | _PyTime_t secs; |
614 | 0 | int res; |
615 | |
|
616 | 0 | res = _PyTime_AsTimeval_impl(t, &secs, us, round); |
617 | |
|
618 | 0 | *p_secs = secs; |
619 | |
|
620 | 0 | if (res < 0 || (_PyTime_t)*p_secs != secs) { |
621 | 0 | error_time_t_overflow(); |
622 | 0 | return -1; |
623 | 0 | } |
624 | 0 | return 0; |
625 | 0 | } |
626 | | |
627 | | |
628 | | #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) |
629 | | int |
630 | | _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts) |
631 | 0 | { |
632 | 0 | _PyTime_t secs, nsec; |
633 | |
|
634 | 0 | secs = t / SEC_TO_NS; |
635 | 0 | nsec = t % SEC_TO_NS; |
636 | 0 | if (nsec < 0) { |
637 | 0 | nsec += SEC_TO_NS; |
638 | 0 | secs -= 1; |
639 | 0 | } |
640 | 0 | ts->tv_sec = (time_t)secs; |
641 | 0 | assert(0 <= nsec && nsec < SEC_TO_NS); |
642 | 0 | ts->tv_nsec = nsec; |
643 | |
|
644 | 0 | if ((_PyTime_t)ts->tv_sec != secs) { |
645 | 0 | error_time_t_overflow(); |
646 | 0 | return -1; |
647 | 0 | } |
648 | 0 | return 0; |
649 | 0 | } |
650 | | #endif |
651 | | |
652 | | static int |
653 | | pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) |
654 | 29 | { |
655 | | #ifdef MS_WINDOWS |
656 | | FILETIME system_time; |
657 | | ULARGE_INTEGER large; |
658 | | |
659 | | assert(info == NULL || raise); |
660 | | |
661 | | GetSystemTimeAsFileTime(&system_time); |
662 | | large.u.LowPart = system_time.dwLowDateTime; |
663 | | large.u.HighPart = system_time.dwHighDateTime; |
664 | | /* 11,644,473,600,000,000,000: number of nanoseconds between |
665 | | the 1st january 1601 and the 1st january 1970 (369 years + 89 leap |
666 | | days). */ |
667 | | *tp = large.QuadPart * 100 - 11644473600000000000; |
668 | | if (info) { |
669 | | DWORD timeAdjustment, timeIncrement; |
670 | | BOOL isTimeAdjustmentDisabled, ok; |
671 | | |
672 | | info->implementation = "GetSystemTimeAsFileTime()"; |
673 | | info->monotonic = 0; |
674 | | ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, |
675 | | &isTimeAdjustmentDisabled); |
676 | | if (!ok) { |
677 | | PyErr_SetFromWindowsErr(0); |
678 | | return -1; |
679 | | } |
680 | | info->resolution = timeIncrement * 1e-7; |
681 | | info->adjustable = 1; |
682 | | } |
683 | | |
684 | | #else /* MS_WINDOWS */ |
685 | 29 | int err; |
686 | 29 | #ifdef HAVE_CLOCK_GETTIME |
687 | 29 | struct timespec ts; |
688 | | #else |
689 | | struct timeval tv; |
690 | | #endif |
691 | | |
692 | 29 | assert(info == NULL || raise); |
693 | | |
694 | 29 | #ifdef HAVE_CLOCK_GETTIME |
695 | 29 | err = clock_gettime(CLOCK_REALTIME, &ts); |
696 | 29 | if (err) { |
697 | 0 | if (raise) { |
698 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
699 | 0 | } |
700 | 0 | return -1; |
701 | 0 | } |
702 | 29 | if (pytime_fromtimespec(tp, &ts, raise) < 0) { |
703 | 0 | return -1; |
704 | 0 | } |
705 | | |
706 | 29 | if (info) { |
707 | 0 | struct timespec res; |
708 | 0 | info->implementation = "clock_gettime(CLOCK_REALTIME)"; |
709 | 0 | info->monotonic = 0; |
710 | 0 | info->adjustable = 1; |
711 | 0 | if (clock_getres(CLOCK_REALTIME, &res) == 0) { |
712 | 0 | info->resolution = res.tv_sec + res.tv_nsec * 1e-9; |
713 | 0 | } |
714 | 0 | else { |
715 | 0 | info->resolution = 1e-9; |
716 | 0 | } |
717 | 0 | } |
718 | | #else /* HAVE_CLOCK_GETTIME */ |
719 | | |
720 | | /* test gettimeofday() */ |
721 | | #ifdef GETTIMEOFDAY_NO_TZ |
722 | | err = gettimeofday(&tv); |
723 | | #else |
724 | | err = gettimeofday(&tv, (struct timezone *)NULL); |
725 | | #endif |
726 | | if (err) { |
727 | | if (raise) { |
728 | | PyErr_SetFromErrno(PyExc_OSError); |
729 | | } |
730 | | return -1; |
731 | | } |
732 | | if (pytime_fromtimeval(tp, &tv, raise) < 0) { |
733 | | return -1; |
734 | | } |
735 | | |
736 | | if (info) { |
737 | | info->implementation = "gettimeofday()"; |
738 | | info->resolution = 1e-6; |
739 | | info->monotonic = 0; |
740 | | info->adjustable = 1; |
741 | | } |
742 | | #endif /* !HAVE_CLOCK_GETTIME */ |
743 | 29 | #endif /* !MS_WINDOWS */ |
744 | 29 | return 0; |
745 | 29 | } |
746 | | |
747 | | _PyTime_t |
748 | | _PyTime_GetSystemClock(void) |
749 | 15 | { |
750 | 15 | _PyTime_t t; |
751 | 15 | if (pygettimeofday(&t, NULL, 0) < 0) { |
752 | | /* should not happen, _PyTime_Init() checked the clock at startup */ |
753 | 0 | Py_UNREACHABLE(); |
754 | 0 | } |
755 | 15 | return t; |
756 | 15 | } |
757 | | |
758 | | int |
759 | | _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info) |
760 | 14 | { |
761 | 14 | return pygettimeofday(t, info, 1); |
762 | 14 | } |
763 | | |
764 | | static int |
765 | | pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise) |
766 | 28 | { |
767 | | #if defined(MS_WINDOWS) |
768 | | ULONGLONG ticks; |
769 | | _PyTime_t t; |
770 | | |
771 | | assert(info == NULL || raise); |
772 | | |
773 | | ticks = GetTickCount64(); |
774 | | Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t)); |
775 | | t = (_PyTime_t)ticks; |
776 | | |
777 | | if (_PyTime_check_mul_overflow(t, MS_TO_NS)) { |
778 | | if (raise) { |
779 | | _PyTime_overflow(); |
780 | | return -1; |
781 | | } |
782 | | /* Hello, time traveler! */ |
783 | | Py_UNREACHABLE(); |
784 | | } |
785 | | *tp = t * MS_TO_NS; |
786 | | |
787 | | if (info) { |
788 | | DWORD timeAdjustment, timeIncrement; |
789 | | BOOL isTimeAdjustmentDisabled, ok; |
790 | | info->implementation = "GetTickCount64()"; |
791 | | info->monotonic = 1; |
792 | | ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, |
793 | | &isTimeAdjustmentDisabled); |
794 | | if (!ok) { |
795 | | PyErr_SetFromWindowsErr(0); |
796 | | return -1; |
797 | | } |
798 | | info->resolution = timeIncrement * 1e-7; |
799 | | info->adjustable = 0; |
800 | | } |
801 | | |
802 | | #elif defined(__APPLE__) |
803 | | static mach_timebase_info_data_t timebase; |
804 | | static uint64_t t0 = 0; |
805 | | uint64_t ticks; |
806 | | |
807 | | if (timebase.denom == 0) { |
808 | | /* According to the Technical Q&A QA1398, mach_timebase_info() cannot |
809 | | fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ |
810 | | (void)mach_timebase_info(&timebase); |
811 | | |
812 | | /* Sanity check: should never occur in practice */ |
813 | | if (timebase.numer < 1 || timebase.denom < 1) { |
814 | | PyErr_SetString(PyExc_RuntimeError, |
815 | | "invalid mach_timebase_info"); |
816 | | return -1; |
817 | | } |
818 | | |
819 | | /* Check that timebase.numer and timebase.denom can be casted to |
820 | | _PyTime_t. In practice, timebase uses uint32_t, so casting cannot |
821 | | overflow. At the end, only make sure that the type is uint32_t |
822 | | (_PyTime_t is 64-bit long). */ |
823 | | assert(sizeof(timebase.numer) < sizeof(_PyTime_t)); |
824 | | assert(sizeof(timebase.denom) < sizeof(_PyTime_t)); |
825 | | |
826 | | /* Make sure that (ticks * timebase.numer) cannot overflow in |
827 | | _PyTime_MulDiv(), with ticks < timebase.denom. |
828 | | |
829 | | Known time bases: |
830 | | |
831 | | * always (1, 1) on Intel |
832 | | * (1000000000, 33333335) or (1000000000, 25000000) on PowerPC |
833 | | |
834 | | None of these time bases can overflow with 64-bit _PyTime_t, but |
835 | | check for overflow, just in case. */ |
836 | | if ((_PyTime_t)timebase.numer > _PyTime_MAX / (_PyTime_t)timebase.denom) { |
837 | | PyErr_SetString(PyExc_OverflowError, |
838 | | "mach_timebase_info is too large"); |
839 | | return -1; |
840 | | } |
841 | | |
842 | | t0 = mach_absolute_time(); |
843 | | } |
844 | | |
845 | | if (info) { |
846 | | info->implementation = "mach_absolute_time()"; |
847 | | info->resolution = (double)timebase.numer / (double)timebase.denom * 1e-9; |
848 | | info->monotonic = 1; |
849 | | info->adjustable = 0; |
850 | | } |
851 | | |
852 | | ticks = mach_absolute_time(); |
853 | | /* Use a "time zero" to reduce precision loss when converting time |
854 | | to floatting point number, as in time.monotonic(). */ |
855 | | ticks -= t0; |
856 | | *tp = _PyTime_MulDiv(ticks, |
857 | | (_PyTime_t)timebase.numer, |
858 | | (_PyTime_t)timebase.denom); |
859 | | |
860 | | #elif defined(__hpux) |
861 | | hrtime_t time; |
862 | | |
863 | | time = gethrtime(); |
864 | | if (time == -1) { |
865 | | if (raise) { |
866 | | PyErr_SetFromErrno(PyExc_OSError); |
867 | | } |
868 | | return -1; |
869 | | } |
870 | | |
871 | | *tp = time; |
872 | | |
873 | | if (info) { |
874 | | info->implementation = "gethrtime()"; |
875 | | info->resolution = 1e-9; |
876 | | info->monotonic = 1; |
877 | | info->adjustable = 0; |
878 | | } |
879 | | |
880 | | #else |
881 | 28 | struct timespec ts; |
882 | | #ifdef CLOCK_HIGHRES |
883 | | const clockid_t clk_id = CLOCK_HIGHRES; |
884 | | const char *implementation = "clock_gettime(CLOCK_HIGHRES)"; |
885 | | #else |
886 | 28 | const clockid_t clk_id = CLOCK_MONOTONIC; |
887 | 28 | const char *implementation = "clock_gettime(CLOCK_MONOTONIC)"; |
888 | 28 | #endif |
889 | | |
890 | 28 | assert(info == NULL || raise); |
891 | | |
892 | 28 | if (clock_gettime(clk_id, &ts) != 0) { |
893 | 0 | if (raise) { |
894 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
895 | 0 | return -1; |
896 | 0 | } |
897 | 0 | return -1; |
898 | 0 | } |
899 | | |
900 | 28 | if (info) { |
901 | 0 | struct timespec res; |
902 | 0 | info->monotonic = 1; |
903 | 0 | info->implementation = implementation; |
904 | 0 | info->adjustable = 0; |
905 | 0 | if (clock_getres(clk_id, &res) != 0) { |
906 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
907 | 0 | return -1; |
908 | 0 | } |
909 | 0 | info->resolution = res.tv_sec + res.tv_nsec * 1e-9; |
910 | 0 | } |
911 | 28 | if (pytime_fromtimespec(tp, &ts, raise) < 0) { |
912 | 0 | return -1; |
913 | 0 | } |
914 | 28 | #endif |
915 | 28 | return 0; |
916 | 28 | } |
917 | | |
918 | | _PyTime_t |
919 | | _PyTime_GetMonotonicClock(void) |
920 | 0 | { |
921 | 0 | _PyTime_t t; |
922 | 0 | if (pymonotonic(&t, NULL, 0) < 0) { |
923 | | /* should not happen, _PyTime_Init() checked that monotonic clock at |
924 | | startup */ |
925 | 0 | Py_UNREACHABLE(); |
926 | 0 | } |
927 | 0 | return t; |
928 | 0 | } |
929 | | |
930 | | int |
931 | | _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) |
932 | 28 | { |
933 | 28 | return pymonotonic(tp, info, 1); |
934 | 28 | } |
935 | | |
936 | | |
937 | | #ifdef MS_WINDOWS |
938 | | static int |
939 | | win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info) |
940 | | { |
941 | | static LONGLONG frequency = 0; |
942 | | static LONGLONG t0 = 0; |
943 | | LARGE_INTEGER now; |
944 | | LONGLONG ticksll; |
945 | | _PyTime_t ticks; |
946 | | |
947 | | if (frequency == 0) { |
948 | | LARGE_INTEGER freq; |
949 | | if (!QueryPerformanceFrequency(&freq)) { |
950 | | PyErr_SetFromWindowsErr(0); |
951 | | return -1; |
952 | | } |
953 | | frequency = freq.QuadPart; |
954 | | |
955 | | /* Sanity check: should never occur in practice */ |
956 | | if (frequency < 1) { |
957 | | PyErr_SetString(PyExc_RuntimeError, |
958 | | "invalid QueryPerformanceFrequency"); |
959 | | return -1; |
960 | | } |
961 | | |
962 | | /* Check that frequency can be casted to _PyTime_t. |
963 | | |
964 | | Make also sure that (ticks * SEC_TO_NS) cannot overflow in |
965 | | _PyTime_MulDiv(), with ticks < frequency. |
966 | | |
967 | | Known QueryPerformanceFrequency() values: |
968 | | |
969 | | * 10,000,000 (10 MHz): 100 ns resolution |
970 | | * 3,579,545 Hz (3.6 MHz): 279 ns resolution |
971 | | |
972 | | None of these frequencies can overflow with 64-bit _PyTime_t, but |
973 | | check for overflow, just in case. */ |
974 | | if (frequency > _PyTime_MAX |
975 | | || frequency > (LONGLONG)_PyTime_MAX / (LONGLONG)SEC_TO_NS) { |
976 | | PyErr_SetString(PyExc_OverflowError, |
977 | | "QueryPerformanceFrequency is too large"); |
978 | | return -1; |
979 | | } |
980 | | |
981 | | QueryPerformanceCounter(&now); |
982 | | t0 = now.QuadPart; |
983 | | } |
984 | | |
985 | | if (info) { |
986 | | info->implementation = "QueryPerformanceCounter()"; |
987 | | info->resolution = 1.0 / (double)frequency; |
988 | | info->monotonic = 1; |
989 | | info->adjustable = 0; |
990 | | } |
991 | | |
992 | | QueryPerformanceCounter(&now); |
993 | | ticksll = now.QuadPart; |
994 | | |
995 | | /* Use a "time zero" to reduce precision loss when converting time |
996 | | to floatting point number, as in time.perf_counter(). */ |
997 | | ticksll -= t0; |
998 | | |
999 | | /* Make sure that casting LONGLONG to _PyTime_t cannot overflow, |
1000 | | both types are signed */ |
1001 | | Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks)); |
1002 | | ticks = (_PyTime_t)ticksll; |
1003 | | |
1004 | | *tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency); |
1005 | | return 0; |
1006 | | } |
1007 | | #endif |
1008 | | |
1009 | | |
1010 | | int |
1011 | | _PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) |
1012 | 14 | { |
1013 | | #ifdef MS_WINDOWS |
1014 | | return win_perf_counter(t, info); |
1015 | | #else |
1016 | 14 | return _PyTime_GetMonotonicClockWithInfo(t, info); |
1017 | 14 | #endif |
1018 | 14 | } |
1019 | | |
1020 | | |
1021 | | _PyTime_t |
1022 | | _PyTime_GetPerfCounter(void) |
1023 | 0 | { |
1024 | 0 | _PyTime_t t; |
1025 | 0 | if (_PyTime_GetPerfCounterWithInfo(&t, NULL)) { |
1026 | 0 | Py_UNREACHABLE(); |
1027 | 0 | } |
1028 | 0 | return t; |
1029 | 0 | } |
1030 | | |
1031 | | |
1032 | | int |
1033 | | _PyTime_Init(void) |
1034 | 14 | { |
1035 | | /* check that time.time(), time.monotonic() and time.perf_counter() clocks |
1036 | | are working properly to not have to check for exceptions at runtime. If |
1037 | | a clock works once, it cannot fail in next calls. */ |
1038 | 14 | _PyTime_t t; |
1039 | 14 | if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0) { |
1040 | 0 | return -1; |
1041 | 0 | } |
1042 | 14 | if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0) { |
1043 | 0 | return -1; |
1044 | 0 | } |
1045 | 14 | if (_PyTime_GetPerfCounterWithInfo(&t, NULL) < 0) { |
1046 | 0 | return -1; |
1047 | 0 | } |
1048 | 14 | return 0; |
1049 | 14 | } |
1050 | | |
1051 | | int |
1052 | | _PyTime_localtime(time_t t, struct tm *tm) |
1053 | 28 | { |
1054 | | #ifdef MS_WINDOWS |
1055 | | int error; |
1056 | | |
1057 | | error = localtime_s(tm, &t); |
1058 | | if (error != 0) { |
1059 | | errno = error; |
1060 | | PyErr_SetFromErrno(PyExc_OSError); |
1061 | | return -1; |
1062 | | } |
1063 | | return 0; |
1064 | | #else /* !MS_WINDOWS */ |
1065 | | |
1066 | | #ifdef _AIX |
1067 | | /* bpo-34373: AIX does not return NULL if t is too small or too large */ |
1068 | | if (t < -2145916800 /* 1902-01-01 */ |
1069 | | || t > 2145916800 /* 2038-01-01 */) { |
1070 | | errno = EINVAL; |
1071 | | PyErr_SetString(PyExc_OverflowError, |
1072 | | "localtime argument out of range"); |
1073 | | return -1; |
1074 | | } |
1075 | | #endif |
1076 | | |
1077 | 28 | errno = 0; |
1078 | 28 | if (localtime_r(&t, tm) == NULL) { |
1079 | 0 | if (errno == 0) { |
1080 | 0 | errno = EINVAL; |
1081 | 0 | } |
1082 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
1083 | 0 | return -1; |
1084 | 0 | } |
1085 | 28 | return 0; |
1086 | 28 | #endif /* MS_WINDOWS */ |
1087 | 28 | } |
1088 | | |
1089 | | int |
1090 | | _PyTime_gmtime(time_t t, struct tm *tm) |
1091 | 0 | { |
1092 | | #ifdef MS_WINDOWS |
1093 | | int error; |
1094 | | |
1095 | | error = gmtime_s(tm, &t); |
1096 | | if (error != 0) { |
1097 | | errno = error; |
1098 | | PyErr_SetFromErrno(PyExc_OSError); |
1099 | | return -1; |
1100 | | } |
1101 | | return 0; |
1102 | | #else /* !MS_WINDOWS */ |
1103 | 0 | if (gmtime_r(&t, tm) == NULL) { |
1104 | 0 | #ifdef EINVAL |
1105 | 0 | if (errno == 0) { |
1106 | 0 | errno = EINVAL; |
1107 | 0 | } |
1108 | 0 | #endif |
1109 | 0 | PyErr_SetFromErrno(PyExc_OSError); |
1110 | 0 | return -1; |
1111 | 0 | } |
1112 | 0 | return 0; |
1113 | 0 | #endif /* MS_WINDOWS */ |
1114 | 0 | } |