/home/mdboom/Work/builds/cpython/Python/pytime.c
Line | Count | Source (jump to first uncovered line) |
1 | #include "Python.h" |
2 | #include "pycore_pymath.h" // _Py_InIntegralTypeRange() |
3 | #ifdef MS_WINDOWS |
4 | # include <winsock2.h> // struct timeval |
5 | #endif |
6 | |
7 | #if defined(__APPLE__) |
8 | # include <mach/mach_time.h> // mach_absolute_time(), mach_timebase_info() |
9 | |
10 | #if defined(__APPLE__) && defined(__has_builtin) |
11 | # if __has_builtin(__builtin_available) |
12 | # define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) |
13 | # endif |
14 | #endif |
15 | #endif |
16 | |
17 | /* To millisecond (10^-3) */ |
18 | #define SEC_TO_MS 1000 |
19 | |
20 | /* To microseconds (10^-6) */ |
21 | #define MS_TO_US 1000 |
22 | #define SEC_TO_US (SEC_TO_MS * MS_TO_US) |
23 | |
24 | /* To nanoseconds (10^-9) */ |
25 | #define US_TO_NS 1000 |
26 | #define MS_TO_NS (MS_TO_US * US_TO_NS) |
27 | #define SEC_TO_NS (SEC_TO_MS * MS_TO_NS) |
28 | |
29 | /* Conversion from nanoseconds */ |
30 | #define NS_TO_MS (1000 * 1000) |
31 | #define NS_TO_US (1000) |
32 | #define NS_TO_100NS (100) |
33 | |
34 | #if SIZEOF_TIME_T == SIZEOF_LONG_LONG |
35 | # define PY_TIME_T_MAX LLONG_MAX |
36 | # define PY_TIME_T_MIN LLONG_MIN |
37 | #elif SIZEOF_TIME_T == SIZEOF_LONG |
38 | # define PY_TIME_T_MAX LONG_MAX |
39 | # define PY_TIME_T_MIN LONG_MIN |
40 | #else |
41 | # error "unsupported time_t size" |
42 | #endif |
43 | |
44 | |
45 | static void |
46 | pytime_time_t_overflow(void) |
47 | { |
48 | PyErr_SetString(PyExc_OverflowError, |
49 | "timestamp out of range for platform time_t"); |
50 | } |
51 | |
52 | |
53 | static void |
54 | pytime_overflow(void) |
55 | { |
56 | PyErr_SetString(PyExc_OverflowError, |
57 | "timestamp too large to convert to C _PyTime_t"); |
58 | } |
59 | |
60 | |
61 | static inline _PyTime_t |
62 | pytime_from_nanoseconds(_PyTime_t t) |
63 | { |
64 | // _PyTime_t is a number of nanoseconds |
65 | return t; |
66 | } |
67 | |
68 | |
69 | static inline _PyTime_t |
70 | pytime_as_nanoseconds(_PyTime_t t) |
71 | { |
72 | // _PyTime_t is a number of nanoseconds: see pytime_from_nanoseconds() |
73 | return t; |
74 | } |
75 | |
76 | |
77 | // Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. |
78 | static inline int |
79 | pytime_add(_PyTime_t *t1, _PyTime_t t2) |
80 | { |
81 | if (t2 > 0 && *t1 > 23.6M _PyTime_MAX23.6M - t2) { Branch (81:9): [True: 23.6M, False: 15.8M]
Branch (81:19): [True: 5, False: 23.6M]
|
82 | *t1 = _PyTime_MAX; |
83 | return -1; |
84 | } |
85 | else if (t2 < 0 && *t1 < 2.60M _PyTime_MIN2.60M - t2) { Branch (85:14): [True: 2.60M, False: 36.8M]
Branch (85:24): [True: 0, False: 2.60M]
|
86 | *t1 = _PyTime_MIN; |
87 | return -1; |
88 | } |
89 | else { |
90 | *t1 += t2; |
91 | return 0; |
92 | } |
93 | } |
94 | |
95 | |
96 | _PyTime_t |
97 | _PyTime_Add(_PyTime_t t1, _PyTime_t t2) |
98 | { |
99 | (void)pytime_add(&t1, t2); |
100 | return t1; |
101 | } |
102 | |
103 | |
104 | static inline int |
105 | pytime_mul_check_overflow(_PyTime_t a, _PyTime_t b) |
106 | { |
107 | if (b != 0) { Branch (107:9): [True: 36.7M, False: 0]
|
108 | assert(b > 0); |
109 | return ((a < 36.7M _PyTime_MIN36.7M / b) || (_PyTime_MAX / b < a)); Branch (109:17): [True: 18.4E, False: 36.7M]
Branch (109:42): [True: 18.4E, False: 36.7M]
|
110 | } |
111 | else { |
112 | return 0; |
113 | } |
114 | } |
115 | |
116 | |
117 | // Compute t * k. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. |
118 | static inline int |
119 | pytime_mul(_PyTime_t *t, _PyTime_t k) |
120 | { |
121 | assert(k >= 0); |
122 | if (pytime_mul_check_overflow(*t, k)) { Branch (122:9): [True: 8, False: 36.7M]
|
123 | *t = (*t >= 0) ? _PyTime_MAX : _PyTime_MIN; Branch (123:14): [True: 4, False: 4]
|
124 | return -1; |
125 | } |
126 | else { |
127 | *t *= k; |
128 | return 0; |
129 | } |
130 | } |
131 | |
132 | |
133 | // Compute t * k. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow. |
134 | static inline _PyTime_t |
135 | _PyTime_Mul(_PyTime_t t, _PyTime_t k) |
136 | { |
137 | (void)pytime_mul(&t, k); |
138 | return t; |
139 | } |
140 | |
141 | |
142 | |
143 | |
144 | _PyTime_t |
145 | _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) |
146 | { |
147 | /* Compute (ticks * mul / div) in two parts to reduce the risk of integer |
148 | overflow: compute the integer part, and then the remaining part. |
149 | |
150 | (ticks * mul) / div == (ticks / div) * mul + (ticks % div) * mul / div |
151 | */ |
152 | _PyTime_t intpart, remaining; |
153 | intpart = ticks / div; |
154 | ticks %= div; |
155 | remaining = _PyTime_Mul(ticks, mul) / div; |
156 | // intpart * mul + remaining |
157 | return _PyTime_Add(_PyTime_Mul(intpart, mul), remaining); |
158 | } |
159 | |
160 | |
161 | time_t |
162 | _PyLong_AsTime_t(PyObject *obj) |
163 | { |
164 | #if SIZEOF_TIME_T == SIZEOF_LONG_LONG |
165 | long long val = PyLong_AsLongLong(obj); |
166 | #elif SIZEOF_TIME_T <= SIZEOF_LONG |
167 | long val = PyLong_AsLong(obj); |
168 | #else |
169 | # error "unsupported time_t size" |
170 | #endif |
171 | if (val == -1 && PyErr_Occurred()27 ) { Branch (171:9): [True: 27, False: 19.8k]
Branch (171:22): [True: 13, False: 14]
|
172 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { Branch (172:13): [True: 0, False: 13]
|
173 | pytime_time_t_overflow(); |
174 | } |
175 | return -1; |
176 | } |
177 | return (time_t)val; |
178 | } |
179 | |
180 | |
181 | PyObject * |
182 | _PyLong_FromTime_t(time_t t) |
183 | { |
184 | #if SIZEOF_TIME_T == SIZEOF_LONG_LONG |
185 | return PyLong_FromLongLong((long long)t); |
186 | #elif SIZEOF_TIME_T <= SIZEOF_LONG |
187 | return PyLong_FromLong((long)t); |
188 | #else |
189 | # error "unsupported time_t size" |
190 | #endif |
191 | } |
192 | |
193 | |
194 | // Convert _PyTime_t to time_t. |
195 | // Return 0 on success. Return -1 and clamp the value on overflow. |
196 | static int |
197 | _PyTime_AsTime_t(_PyTime_t t, time_t *t2) |
198 | { |
199 | #if SIZEOF_TIME_T < _SIZEOF_PYTIME_T |
200 | if ((_PyTime_t)PY_TIME_T_MAX < t) { |
201 | *t2 = PY_TIME_T_MAX; |
202 | return -1; |
203 | } |
204 | if (t < (_PyTime_t)PY_TIME_T_MIN) { |
205 | *t2 = PY_TIME_T_MIN; |
206 | return -1; |
207 | } |
208 | #endif |
209 | *t2 = (time_t)t; |
210 | return 0; |
211 | } |
212 | |
213 | |
214 | #ifdef MS_WINDOWS |
215 | // Convert _PyTime_t to long. |
216 | // Return 0 on success. Return -1 and clamp the value on overflow. |
217 | static int |
218 | _PyTime_AsLong(_PyTime_t t, long *t2) |
219 | { |
220 | #if SIZEOF_LONG < _SIZEOF_PYTIME_T |
221 | if ((_PyTime_t)LONG_MAX < t) { |
222 | *t2 = LONG_MAX; |
223 | return -1; |
224 | } |
225 | if (t < (_PyTime_t)LONG_MIN) { |
226 | *t2 = LONG_MIN; |
227 | return -1; |
228 | } |
229 | #endif |
230 | *t2 = (long)t; |
231 | return 0; |
232 | } |
233 | #endif |
234 | |
235 | |
236 | /* Round to nearest with ties going to nearest even integer |
237 | (_PyTime_ROUND_HALF_EVEN) */ |
238 | static double |
239 | pytime_round_half_even(double x) |
240 | { |
241 | double rounded = round(x); |
242 | if (fabs(x-rounded) == 0.5) { Branch (242:9): [True: 52, False: 1.51k]
|
243 | /* halfway case: round to even */ |
244 | rounded = 2.0 * round(x / 2.0); |
245 | } |
246 | return rounded; |
247 | } |
248 | |
249 | |
250 | static double |
251 | pytime_round(double x, _PyTime_round_t round) |
252 | { |
253 | /* volatile avoids optimization changing how numbers are rounded */ |
254 | volatile double d; |
255 | |
256 | d = x; |
257 | if (round == _PyTime_ROUND_HALF_EVEN) { Branch (257:9): [True: 1.56k, False: 186k]
|
258 | d = pytime_round_half_even(d); |
259 | } |
260 | else if (round == _PyTime_ROUND_CEILING) { Branch (260:14): [True: 27.5k, False: 158k]
|
261 | d = ceil(d); |
262 | } |
263 | else if (round == _PyTime_ROUND_FLOOR) { Branch (263:14): [True: 16.3k, False: 142k]
|
264 | d = floor(d); |
265 | } |
266 | else { |
267 | assert(round == _PyTime_ROUND_UP); |
268 | d = (d >= 0.0) ? ceil(d)141k : floor(d)484 ; Branch (268:13): [True: 141k, False: 484]
|
269 | } |
270 | return d; |
271 | } |
272 | |
273 | |
274 | static int |
275 | pytime_double_to_denominator(double d, time_t *sec, long *numerator, |
276 | long idenominator, _PyTime_round_t round) |
277 | { |
278 | double denominator = (double)idenominator; |
279 | double intpart; |
280 | /* volatile avoids optimization changing how numbers are rounded */ |
281 | volatile double floatpart; |
282 | |
283 | floatpart = modf(d, &intpart); |
284 | |
285 | floatpart *= denominator; |
286 | floatpart = pytime_round(floatpart, round); |
287 | if (floatpart >= denominator) { Branch (287:9): [True: 30, False: 2.98k]
|
288 | floatpart -= denominator; |
289 | intpart += 1.0; |
290 | } |
291 | else if (floatpart < 0) { Branch (291:14): [True: 737, False: 2.25k]
|
292 | floatpart += denominator; |
293 | intpart -= 1.0; |
294 | } |
295 | assert(0.0 <= floatpart && floatpart < denominator); |
296 | |
297 | if (!_Py_InIntegralTypeRange(time_t, intpart)) { |
298 | pytime_time_t_overflow(); |
299 | return -1; |
300 | } |
301 | *sec = (time_t)intpart; |
302 | *numerator = (long)floatpart; |
303 | assert(0 <= *numerator && *numerator < idenominator); |
304 | return 0; |
305 | } |
306 | |
307 | |
308 | static int |
309 | pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator, |
310 | long denominator, _PyTime_round_t round) |
311 | { |
312 | assert(denominator >= 1); |
313 | |
314 | if (PyFloat_Check(obj)) { |
315 | double d = PyFloat_AsDouble(obj); |
316 | if (Py_IS_NAN(d)) { |
317 | *numerator = 0; |
318 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
319 | return -1; |
320 | } |
321 | return pytime_double_to_denominator(d, sec, numerator, |
322 | denominator, round); |
323 | } |
324 | else { |
325 | *sec = _PyLong_AsTime_t(obj); |
326 | *numerator = 0; |
327 | if (*sec == (time_t)-1 && PyErr_Occurred()21 ) { Branch (327:13): [True: 21, False: 1.67k]
Branch (327:35): [True: 13, False: 8]
|
328 | return -1; |
329 | } |
330 | return 0; |
331 | } |
332 | } |
333 | |
334 | |
335 | int |
336 | _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) |
337 | { |
338 | if (PyFloat_Check(obj)) { |
339 | double intpart; |
340 | /* volatile avoids optimization changing how numbers are rounded */ |
341 | volatile double d; |
342 | |
343 | d = PyFloat_AsDouble(obj); |
344 | if (Py_IS_NAN(d)) { |
345 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
346 | return -1; |
347 | } |
348 | |
349 | d = pytime_round(d, round); |
350 | (void)modf(d, &intpart); |
351 | |
352 | if (!_Py_InIntegralTypeRange(time_t, intpart)) { |
353 | pytime_time_t_overflow(); |
354 | return -1; |
355 | } |
356 | *sec = (time_t)intpart; |
357 | return 0; |
358 | } |
359 | else { |
360 | *sec = _PyLong_AsTime_t(obj); |
361 | if (*sec == (time_t)-1 && PyErr_Occurred()6 ) { Branch (361:13): [True: 6, False: 911]
Branch (361:35): [True: 0, False: 6]
|
362 | return -1; |
363 | } |
364 | return 0; |
365 | } |
366 | } |
367 | |
368 | |
369 | int |
370 | _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, |
371 | _PyTime_round_t round) |
372 | { |
373 | return pytime_object_to_denominator(obj, sec, nsec, SEC_TO_NS, round); |
374 | } |
375 | |
376 | |
377 | int |
378 | _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, |
379 | _PyTime_round_t round) |
380 | { |
381 | return pytime_object_to_denominator(obj, sec, usec, SEC_TO_US, round); |
382 | } |
383 | |
384 | |
385 | _PyTime_t |
386 | _PyTime_FromSeconds(int seconds) |
387 | { |
388 | /* ensure that integer overflow cannot happen, int type should have 32 |
389 | bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_NS takes 30 |
390 | bits). */ |
391 | static_assert(INT_MAX <= _PyTime_MAX / SEC_TO_NS, "_PyTime_t overflow"); |
392 | static_assert(INT_MIN >= _PyTime_MIN / SEC_TO_NS, "_PyTime_t underflow"); |
393 | |
394 | _PyTime_t t = (_PyTime_t)seconds; |
395 | assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS) |
396 | || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS)); |
397 | t *= SEC_TO_NS; |
398 | return pytime_from_nanoseconds(t); |
399 | } |
400 | |
401 | |
402 | _PyTime_t |
403 | _PyTime_FromNanoseconds(_PyTime_t ns) |
404 | { |
405 | return pytime_from_nanoseconds(ns); |
406 | } |
407 | |
408 | |
409 | _PyTime_t |
410 | _PyTime_FromMicrosecondsClamp(_PyTime_t us) |
411 | { |
412 | _PyTime_t ns = _PyTime_Mul(us, US_TO_NS); |
413 | return pytime_from_nanoseconds(ns); |
414 | } |
415 | |
416 | |
417 | int |
418 | _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) |
419 | { |
420 | |
421 | if (!PyLong_Check(obj)) { Branch (421:9): [True: 4, False: 4.97k]
|
422 | PyErr_Format(PyExc_TypeError, "expect int, got %s", |
423 | Py_TYPE(obj)->tp_name); |
424 | return -1; |
425 | } |
426 | |
427 | static_assert(sizeof(long long) == sizeof(_PyTime_t), |
428 | "_PyTime_t is not long long"); |
429 | long long nsec = PyLong_AsLongLong(obj); |
430 | if (nsec == -1 && PyErr_Occurred()44 ) { Branch (430:9): [True: 44, False: 4.93k]
Branch (430:23): [True: 24, False: 20]
|
431 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { Branch (431:13): [True: 24, False: 0]
|
432 | pytime_overflow(); |
433 | } |
434 | return -1; |
435 | } |
436 | |
437 | _PyTime_t t = (_PyTime_t)nsec; |
438 | *tp = pytime_from_nanoseconds(t); |
439 | return 0; |
440 | } |
441 | |
442 | |
443 | #ifdef HAVE_CLOCK_GETTIME |
444 | static int |
445 | pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise_exc) |
446 | { |
447 | _PyTime_t t, tv_nsec; |
448 | |
449 | static_assert(sizeof(ts->tv_sec) <= sizeof(_PyTime_t), |
450 | "timespec.tv_sec is larger than _PyTime_t"); |
451 | t = (_PyTime_t)ts->tv_sec; |
452 | |
453 | int res1 = pytime_mul(&t, SEC_TO_NS); |
454 | |
455 | tv_nsec = ts->tv_nsec; |
456 | int res2 = pytime_add(&t, tv_nsec); |
457 | |
458 | *tp = pytime_from_nanoseconds(t); |
459 | |
460 | if (raise_exc && (6.86M res1 < 06.86M || res2 < 06.86M )) { Branch (460:9): [True: 6.86M, False: 16.3M]
Branch (460:23): [True: 0, False: 6.86M]
Branch (460:35): [True: 0, False: 6.86M]
|
461 | pytime_overflow(); |
462 | return -1; |
463 | } |
464 | return 0; |
465 | } |
466 | |
467 | int |
468 | _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) |
469 | { |
470 | return pytime_fromtimespec(tp, ts, 1); |
471 | } |
472 | #endif |
473 | |
474 | |
475 | #ifndef MS_WINDOWS |
476 | static int |
477 | pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise_exc) |
478 | { |
479 | static_assert(sizeof(tv->tv_sec) <= sizeof(_PyTime_t), |
480 | "timeval.tv_sec is larger than _PyTime_t"); |
481 | _PyTime_t t = (_PyTime_t)tv->tv_sec; |
482 |
|
483 | int res1 = pytime_mul(&t, SEC_TO_NS); |
484 |
|
485 | _PyTime_t usec = (_PyTime_t)tv->tv_usec * US_TO_NS; |
486 | int res2 = pytime_add(&t, usec); |
487 |
|
488 | *tp = pytime_from_nanoseconds(t); |
489 |
|
490 | if (raise_exc && (res1 < 0 || res2 < 0)) { Branch (490:9): [True: 0, False: 0]
Branch (490:23): [True: 0, False: 0]
Branch (490:35): [True: 0, False: 0]
|
491 | pytime_overflow(); |
492 | return -1; |
493 | } |
494 | return 0; |
495 | } |
496 | |
497 | |
498 | int |
499 | _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv) |
500 | { |
501 | return pytime_fromtimeval(tp, tv, 1); |
502 | } |
503 | #endif |
504 | |
505 | |
506 | static int |
507 | pytime_from_double(_PyTime_t *tp, double value, _PyTime_round_t round, |
508 | long unit_to_ns) |
509 | { |
510 | /* volatile avoids optimization changing how numbers are rounded */ |
511 | volatile double d; |
512 | |
513 | /* convert to a number of nanoseconds */ |
514 | d = value; |
515 | d *= (double)unit_to_ns; |
516 | d = pytime_round(d, round); |
517 | |
518 | if (!_Py_InIntegralTypeRange(_PyTime_t, d)) { |
519 | pytime_overflow(); |
520 | return -1; |
521 | } |
522 | _PyTime_t ns = (_PyTime_t)d; |
523 | |
524 | *tp = pytime_from_nanoseconds(ns); |
525 | return 0; |
526 | } |
527 | |
528 | |
529 | static int |
530 | pytime_from_object(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round, |
531 | long unit_to_ns) |
532 | { |
533 | if (PyFloat_Check(obj)) { |
534 | double d; |
535 | d = PyFloat_AsDouble(obj); |
536 | if (Py_IS_NAN(d)) { |
537 | PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); |
538 | return -1; |
539 | } |
540 | return pytime_from_double(tp, d, round, unit_to_ns); |
541 | } |
542 | else { |
543 | long long sec = PyLong_AsLongLong(obj); |
544 | if (sec == -1 && PyErr_Occurred()4.77k ) { Branch (544:13): [True: 4.77k, False: 53.3k]
Branch (544:26): [True: 6, False: 4.76k]
|
545 | if (PyErr_ExceptionMatches(PyExc_OverflowError)) { Branch (545:17): [True: 1, False: 5]
|
546 | pytime_overflow(); |
547 | } |
548 | return -1; |
549 | } |
550 | |
551 | static_assert(sizeof(long long) <= sizeof(_PyTime_t), |
552 | "_PyTime_t is smaller than long long"); |
553 | _PyTime_t ns = (_PyTime_t)sec; |
554 | if (pytime_mul(&ns, unit_to_ns) < 0) { Branch (554:13): [True: 8, False: 58.1k]
|
555 | pytime_overflow(); |
556 | return -1; |
557 | } |
558 | |
559 | *tp = pytime_from_nanoseconds(ns); |
560 | return 0; |
561 | } |
562 | } |
563 | |
564 | |
565 | int |
566 | _PyTime_FromSecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round) |
567 | { |
568 | return pytime_from_object(tp, obj, round, SEC_TO_NS); |
569 | } |
570 | |
571 | |
572 | int |
573 | _PyTime_FromMillisecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round) |
574 | { |
575 | return pytime_from_object(tp, obj, round, MS_TO_NS); |
576 | } |
577 | |
578 | |
579 | double |
580 | _PyTime_AsSecondsDouble(_PyTime_t t) |
581 | { |
582 | /* volatile avoids optimization changing how numbers are rounded */ |
583 | volatile double d; |
584 | |
585 | _PyTime_t ns = pytime_as_nanoseconds(t); |
586 | if (ns % SEC_TO_NS == 0) { Branch (586:9): [True: 7.81k, False: 6.77M]
|
587 | /* Divide using integers to avoid rounding issues on the integer part. |
588 | 1e-9 cannot be stored exactly in IEEE 64-bit. */ |
589 | _PyTime_t secs = ns / SEC_TO_NS; |
590 | d = (double)secs; |
591 | } |
592 | else { |
593 | d = (double)ns; |
594 | d /= 1e9; |
595 | } |
596 | return d; |
597 | } |
598 | |
599 | |
600 | PyObject * |
601 | _PyTime_AsNanosecondsObject(_PyTime_t t) |
602 | { |
603 | _PyTime_t ns = pytime_as_nanoseconds(t); |
604 | static_assert(sizeof(long long) >= sizeof(_PyTime_t), |
605 | "_PyTime_t is larger than long long"); |
606 | return PyLong_FromLongLong((long long)ns); |
607 | } |
608 | |
609 | |
610 | static _PyTime_t |
611 | pytime_divide_round_up(const _PyTime_t t, const _PyTime_t k) |
612 | { |
613 | assert(k > 1); |
614 | if (t >= 0) { Branch (614:9): [True: 987k, False: 712]
|
615 | // Don't use (t + k - 1) / k to avoid integer overflow |
616 | // if t is equal to _PyTime_MAX |
617 | _PyTime_t q = t / k; |
618 | if (t % k) { Branch (618:13): [True: 20.0k, False: 967k]
|
619 | q += 1; |
620 | } |
621 | return q; |
622 | } |
623 | else { |
624 | // Don't use (t - (k - 1)) / k to avoid integer overflow |
625 | // if t is equals to _PyTime_MIN. |
626 | _PyTime_t q = t / k; |
627 | if (t % k) { Branch (627:13): [True: 286, False: 426]
|
628 | q -= 1; |
629 | } |
630 | return q; |
631 | } |
632 | } |
633 | |
634 | |
635 | static _PyTime_t |
636 | pytime_divide(const _PyTime_t t, const _PyTime_t k, |
637 | const _PyTime_round_t round) |
638 | { |
639 | assert(k > 1); |
640 | if (round == _PyTime_ROUND_HALF_EVEN) { Branch (640:9): [True: 699, False: 5.60M]
|
641 | _PyTime_t x = t / k; |
642 | _PyTime_t r = t % k; |
643 | _PyTime_t abs_r = Py_ABS(r); |
644 | if (abs_r > k / 2 || (607 abs_r == k / 2607 && (30 Py_ABS30 (x) & 1))) { Branch (644:13): [True: 92, False: 607]
Branch (644:31): [True: 30, False: 577]
Branch (644:49): [True: 12, False: 18]
|
645 | if (t >= 0) { Branch (645:17): [True: 52, False: 52]
|
646 | x++; |
647 | } |
648 | else { |
649 | x--; |
650 | } |
651 | } |
652 | return x; |
653 | } |
654 | else if (round == _PyTime_ROUND_CEILING) { Branch (654:14): [True: 5.52M, False: 81.1k]
|
655 | if (t >= 0) { Branch (655:13): [True: 907k, False: 4.61M]
|
656 | return pytime_divide_round_up(t, k); |
657 | } |
658 | else { |
659 | return t / k; |
660 | } |
661 | } |
662 | else if (round == _PyTime_ROUND_FLOOR){ Branch (662:14): [True: 759, False: 80.4k]
|
663 | if (t >= 0) { Branch (663:13): [True: 411, False: 348]
|
664 | return t / k; |
665 | } |
666 | else { |
667 | return pytime_divide_round_up(t, k); |
668 | } |
669 | } |
670 | else { |
671 | assert(round == _PyTime_ROUND_UP); |
672 | return pytime_divide_round_up(t, k); |
673 | } |
674 | } |
675 | |
676 | |
677 | // Compute (t / k, t % k) in (pq, pr). |
678 | // Make sure that 0 <= pr < k. |
679 | // Return 0 on success. |
680 | // Return -1 on underflow and store (_PyTime_MIN, 0) in (pq, pr). |
681 | static int |
682 | pytime_divmod(const _PyTime_t t, const _PyTime_t k, |
683 | _PyTime_t *pq, _PyTime_t *pr) |
684 | { |
685 | assert(k > 1); |
686 | _PyTime_t q = t / k; |
687 | _PyTime_t r = t % k; |
688 | if (r < 0) { Branch (688:9): [True: 607, False: 16.2M]
|
689 | if (q == _PyTime_MIN) { Branch (689:13): [True: 0, False: 607]
|
690 | *pq = _PyTime_MIN; |
691 | *pr = 0; |
692 | return -1; |
693 | } |
694 | r += k; |
695 | q -= 1; |
696 | } |
697 | assert(0 <= r && r < k); |
698 | |
699 | *pq = q; |
700 | *pr = r; |
701 | return 0; |
702 | } |
703 | |
704 | |
705 | _PyTime_t |
706 | _PyTime_AsNanoseconds(_PyTime_t t) |
707 | { |
708 | return pytime_as_nanoseconds(t); |
709 | } |
710 | |
711 | |
712 | #ifdef MS_WINDOWS |
713 | _PyTime_t |
714 | _PyTime_As100Nanoseconds(_PyTime_t t, _PyTime_round_t round) |
715 | { |
716 | _PyTime_t ns = pytime_as_nanoseconds(t); |
717 | return pytime_divide(ns, NS_TO_100NS, round); |
718 | } |
719 | #endif |
720 | |
721 | |
722 | _PyTime_t |
723 | _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) |
724 | { |
725 | _PyTime_t ns = pytime_as_nanoseconds(t); |
726 | return pytime_divide(ns, NS_TO_US, round); |
727 | } |
728 | |
729 | |
730 | _PyTime_t |
731 | _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) |
732 | { |
733 | _PyTime_t ns = pytime_as_nanoseconds(t); |
734 | return pytime_divide(ns, NS_TO_MS, round); |
735 | } |
736 | |
737 | |
738 | static int |
739 | pytime_as_timeval(_PyTime_t t, _PyTime_t *ptv_sec, int *ptv_usec, |
740 | _PyTime_round_t round) |
741 | { |
742 | _PyTime_t ns = pytime_as_nanoseconds(t); |
743 | _PyTime_t us = pytime_divide(ns, US_TO_NS, round); |
744 | |
745 | _PyTime_t tv_sec, tv_usec; |
746 | int res = pytime_divmod(us, SEC_TO_US, &tv_sec, &tv_usec); |
747 | *ptv_sec = tv_sec; |
748 | *ptv_usec = (int)tv_usec; |
749 | return res; |
750 | } |
751 | |
752 | |
753 | static int |
754 | pytime_as_timeval_struct(_PyTime_t t, struct timeval *tv, |
755 | _PyTime_round_t round, int raise_exc) |
756 | { |
757 | _PyTime_t tv_sec; |
758 | int tv_usec; |
759 | int res = pytime_as_timeval(t, &tv_sec, &tv_usec, round); |
760 | int res2; |
761 | #ifdef MS_WINDOWS |
762 | // On Windows, timeval.tv_sec type is long |
763 | res2 = _PyTime_AsLong(tv_sec, &tv->tv_sec); |
764 | #else |
765 | res2 = _PyTime_AsTime_t(tv_sec, &tv->tv_sec); |
766 | #endif |
767 | if (res2 < 0) { Branch (767:9): [True: 0, False: 54.3k]
|
768 | tv_usec = 0; |
769 | } |
770 | tv->tv_usec = tv_usec; |
771 | |
772 | if (raise_exc && (54.3k res < 054.3k || res2 < 054.3k )) { Branch (772:9): [True: 54.3k, False: 5]
Branch (772:23): [True: 0, False: 54.3k]
Branch (772:34): [True: 0, False: 54.3k]
|
773 | pytime_time_t_overflow(); |
774 | return -1; |
775 | } |
776 | return 0; |
777 | } |
778 | |
779 | |
780 | int |
781 | _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) |
782 | { |
783 | return pytime_as_timeval_struct(t, tv, round, 1); |
784 | } |
785 | |
786 | |
787 | void |
788 | _PyTime_AsTimeval_clamp(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) |
789 | { |
790 | (void)pytime_as_timeval_struct(t, tv, round, 0); |
791 | } |
792 | |
793 | |
794 | int |
795 | _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, |
796 | _PyTime_round_t round) |
797 | { |
798 | _PyTime_t secs; |
799 | if (pytime_as_timeval(t, &secs, us, round) < 0) { Branch (799:9): [True: 0, False: 60]
|
800 | pytime_time_t_overflow(); |
801 | return -1; |
802 | } |
803 | |
804 | if (_PyTime_AsTime_t(secs, p_secs) < 0) { Branch (804:9): [True: 0, False: 60]
|
805 | pytime_time_t_overflow(); |
806 | return -1; |
807 | } |
808 | return 0; |
809 | } |
810 | |
811 | |
812 | #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE) |
813 | static int |
814 | pytime_as_timespec(_PyTime_t t, struct timespec *ts, int raise_exc) |
815 | { |
816 | _PyTime_t ns = pytime_as_nanoseconds(t); |
817 | _PyTime_t tv_sec, tv_nsec; |
818 | int res = pytime_divmod(ns, SEC_TO_NS, &tv_sec, &tv_nsec); |
819 | |
820 | int res2 = _PyTime_AsTime_t(tv_sec, &ts->tv_sec); |
821 | if (res2 < 0) { Branch (821:9): [True: 0, False: 16.2M]
|
822 | tv_nsec = 0; |
823 | } |
824 | ts->tv_nsec = tv_nsec; |
825 | |
826 | if (raise_exc && (90.2k res < 090.2k || res2 < 090.2k )) { Branch (826:9): [True: 90.2k, False: 16.1M]
Branch (826:23): [True: 0, False: 90.2k]
Branch (826:34): [True: 0, False: 90.2k]
|
827 | pytime_time_t_overflow(); |
828 | return -1; |
829 | } |
830 | return 0; |
831 | } |
832 | |
833 | void |
834 | _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts) |
835 | { |
836 | (void)pytime_as_timespec(t, ts, 0); |
837 | } |
838 | |
839 | int |
840 | _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts) |
841 | { |
842 | return pytime_as_timespec(t, ts, 1); |
843 | } |
844 | #endif |
845 | |
846 | |
847 | static int |
848 | py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) |
849 | { |
850 | assert(info == NULL || raise_exc); |
851 | |
852 | #ifdef MS_WINDOWS |
853 | FILETIME system_time; |
854 | ULARGE_INTEGER large; |
855 | |
856 | GetSystemTimeAsFileTime(&system_time); |
857 | large.u.LowPart = system_time.dwLowDateTime; |
858 | large.u.HighPart = system_time.dwHighDateTime; |
859 | /* 11,644,473,600,000,000,000: number of nanoseconds between |
860 | the 1st january 1601 and the 1st january 1970 (369 years + 89 leap |
861 | days). */ |
862 | _PyTime_t ns = large.QuadPart * 100 - 11644473600000000000; |
863 | *tp = pytime_from_nanoseconds(ns); |
864 | if (info) { |
865 | DWORD timeAdjustment, timeIncrement; |
866 | BOOL isTimeAdjustmentDisabled, ok; |
867 | |
868 | info->implementation = "GetSystemTimeAsFileTime()"; |
869 | info->monotonic = 0; |
870 | ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, |
871 | &isTimeAdjustmentDisabled); |
872 | if (!ok) { |
873 | PyErr_SetFromWindowsErr(0); |
874 | return -1; |
875 | } |
876 | info->resolution = timeIncrement * 1e-7; |
877 | info->adjustable = 1; |
878 | } |
879 | |
880 | #else /* MS_WINDOWS */ |
881 | int err; |
882 | #if defined(HAVE_CLOCK_GETTIME) |
883 | struct timespec ts; |
884 | #endif |
885 | |
886 | #if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__) |
887 | struct timeval tv; |
888 | #endif |
889 | |
890 | #ifdef HAVE_CLOCK_GETTIME |
891 | |
892 | #ifdef HAVE_CLOCK_GETTIME_RUNTIME |
893 | if (HAVE_CLOCK_GETTIME_RUNTIME) { |
894 | #endif |
895 | |
896 | err = clock_gettime(CLOCK_REALTIME, &ts); |
897 | if (err) { Branch (897:9): [True: 0, False: 2.84M]
|
898 | if (raise_exc) { Branch (898:13): [True: 0, False: 0]
|
899 | PyErr_SetFromErrno(PyExc_OSError); |
900 | } |
901 | return -1; |
902 | } |
903 | if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) { Branch (903:9): [True: 0, False: 2.84M]
|
904 | return -1; |
905 | } |
906 | |
907 | if (info) { Branch (907:9): [True: 2, False: 2.84M]
|
908 | struct timespec res; |
909 | info->implementation = "clock_gettime(CLOCK_REALTIME)"; |
910 | info->monotonic = 0; |
911 | info->adjustable = 1; |
912 | if (clock_getres(CLOCK_REALTIME, &res) == 0) { Branch (912:13): [True: 2, False: 0]
|
913 | info->resolution = res.tv_sec + res.tv_nsec * 1e-9; |
914 | } |
915 | else { |
916 | info->resolution = 1e-9; |
917 | } |
918 | } |
919 | |
920 | #ifdef HAVE_CLOCK_GETTIME_RUNTIME |
921 | } |
922 | else { |
923 | #endif |
924 | |
925 | #endif |
926 | |
927 | #if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME) |
928 | |
929 | /* test gettimeofday() */ |
930 | err = gettimeofday(&tv, (struct timezone *)NULL); |
931 | if (err) { |
932 | if (raise_exc) { |
933 | PyErr_SetFromErrno(PyExc_OSError); |
934 | } |
935 | return -1; |
936 | } |
937 | if (pytime_fromtimeval(tp, &tv, raise_exc) < 0) { |
938 | return -1; |
939 | } |
940 | |
941 | if (info) { |
942 | info->implementation = "gettimeofday()"; |
943 | info->resolution = 1e-6; |
944 | info->monotonic = 0; |
945 | info->adjustable = 1; |
946 | } |
947 | |
948 | #if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME) |
949 | } /* end of availibity block */ |
950 | #endif |
951 | |
952 | #endif /* !HAVE_CLOCK_GETTIME */ |
953 | #endif /* !MS_WINDOWS */ |
954 | return 0; |
955 | } |
956 | |
957 | |
958 | _PyTime_t |
959 | _PyTime_GetSystemClock(void) |
960 | { |
961 | _PyTime_t t; |
962 | if (py_get_system_clock(&t, NULL, 0) < 0) { Branch (962:9): [True: 0, False: 60]
|
963 | // If clock_gettime(CLOCK_REALTIME) or gettimeofday() fails: |
964 | // silently ignore the failure and return 0. |
965 | t = 0; |
966 | } |
967 | return t; |
968 | } |
969 | |
970 | |
971 | int |
972 | _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info) |
973 | { |
974 | return py_get_system_clock(t, info, 1); |
975 | } |
976 | |
977 | |
978 | #ifdef __APPLE__ |
979 | static int |
980 | py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise) |
981 | { |
982 | static mach_timebase_info_data_t timebase; |
983 | /* According to the Technical Q&A QA1398, mach_timebase_info() cannot |
984 | fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ |
985 | (void)mach_timebase_info(&timebase); |
986 | |
987 | /* Sanity check: should never occur in practice */ |
988 | if (timebase.numer < 1 || timebase.denom < 1) { |
989 | if (raise) { |
990 | PyErr_SetString(PyExc_RuntimeError, |
991 | "invalid mach_timebase_info"); |
992 | } |
993 | return -1; |
994 | } |
995 | |
996 | /* Check that timebase.numer and timebase.denom can be casted to |
997 | _PyTime_t. In practice, timebase uses uint32_t, so casting cannot |
998 | overflow. At the end, only make sure that the type is uint32_t |
999 | (_PyTime_t is 64-bit long). */ |
1000 | static_assert(sizeof(timebase.numer) <= sizeof(_PyTime_t), |
1001 | "timebase.numer is larger than _PyTime_t"); |
1002 | static_assert(sizeof(timebase.denom) <= sizeof(_PyTime_t), |
1003 | "timebase.denom is larger than _PyTime_t"); |
1004 | |
1005 | /* Make sure that _PyTime_MulDiv(ticks, timebase_numer, timebase_denom) |
1006 | cannot overflow. |
1007 | |
1008 | Known time bases: |
1009 | |
1010 | * (1, 1) on Intel |
1011 | * (1000000000, 33333335) or (1000000000, 25000000) on PowerPC |
1012 | |
1013 | None of these time bases can overflow with 64-bit _PyTime_t, but |
1014 | check for overflow, just in case. */ |
1015 | if ((_PyTime_t)timebase.numer > _PyTime_MAX / (_PyTime_t)timebase.denom) { |
1016 | if (raise) { |
1017 | PyErr_SetString(PyExc_OverflowError, |
1018 | "mach_timebase_info is too large"); |
1019 | } |
1020 | return -1; |
1021 | } |
1022 | |
1023 | *pnumer = (_PyTime_t)timebase.numer; |
1024 | *pdenom = (_PyTime_t)timebase.denom; |
1025 | return 0; |
1026 | } |
1027 | #endif |
1028 | |
1029 | |
1030 | static int |
1031 | py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) |
1032 | { |
1033 | assert(info == NULL || raise_exc); |
1034 | |
1035 | #if defined(MS_WINDOWS) |
1036 | ULONGLONG ticks = GetTickCount64(); |
1037 | static_assert(sizeof(ticks) <= sizeof(_PyTime_t), |
1038 | "ULONGLONG is larger than _PyTime_t"); |
1039 | _PyTime_t t; |
1040 | if (ticks <= (ULONGLONG)_PyTime_MAX) { |
1041 | t = (_PyTime_t)ticks; |
1042 | } |
1043 | else { |
1044 | // GetTickCount64() maximum is larger than _PyTime_t maximum: |
1045 | // ULONGLONG is unsigned, whereas _PyTime_t is signed. |
1046 | t = _PyTime_MAX; |
1047 | } |
1048 | |
1049 | int res = pytime_mul(&t, MS_TO_NS); |
1050 | *tp = t; |
1051 | |
1052 | if (raise_exc && res < 0) { |
1053 | pytime_overflow(); |
1054 | return -1; |
1055 | } |
1056 | |
1057 | if (info) { |
1058 | DWORD timeAdjustment, timeIncrement; |
1059 | BOOL isTimeAdjustmentDisabled, ok; |
1060 | info->implementation = "GetTickCount64()"; |
1061 | info->monotonic = 1; |
1062 | ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, |
1063 | &isTimeAdjustmentDisabled); |
1064 | if (!ok) { |
1065 | PyErr_SetFromWindowsErr(0); |
1066 | return -1; |
1067 | } |
1068 | info->resolution = timeIncrement * 1e-7; |
1069 | info->adjustable = 0; |
1070 | } |
1071 | |
1072 | #elif defined(__APPLE__) |
1073 | static _PyTime_t timebase_numer = 0; |
1074 | static _PyTime_t timebase_denom = 0; |
1075 | if (timebase_denom == 0) { |
1076 | if (py_mach_timebase_info(&timebase_numer, &timebase_denom, raise_exc) < 0) { |
1077 | return -1; |
1078 | } |
1079 | } |
1080 | |
1081 | if (info) { |
1082 | info->implementation = "mach_absolute_time()"; |
1083 | info->resolution = (double)timebase_numer / (double)timebase_denom * 1e-9; |
1084 | info->monotonic = 1; |
1085 | info->adjustable = 0; |
1086 | } |
1087 | |
1088 | uint64_t uticks = mach_absolute_time(); |
1089 | // unsigned => signed |
1090 | assert(uticks <= (uint64_t)_PyTime_MAX); |
1091 | _PyTime_t ticks = (_PyTime_t)uticks; |
1092 | |
1093 | _PyTime_t ns = _PyTime_MulDiv(ticks, timebase_numer, timebase_denom); |
1094 | *tp = pytime_from_nanoseconds(ns); |
1095 | |
1096 | #elif defined(__hpux) |
1097 | hrtime_t time; |
1098 | |
1099 | time = gethrtime(); |
1100 | if (time == -1) { |
1101 | if (raise_exc) { |
1102 | PyErr_SetFromErrno(PyExc_OSError); |
1103 | } |
1104 | return -1; |
1105 | } |
1106 | |
1107 | *tp = pytime_from_nanoseconds(time); |
1108 | |
1109 | if (info) { |
1110 | info->implementation = "gethrtime()"; |
1111 | info->resolution = 1e-9; |
1112 | info->monotonic = 1; |
1113 | info->adjustable = 0; |
1114 | } |
1115 | |
1116 | #else |
1117 | |
1118 | #ifdef CLOCK_HIGHRES |
1119 | const clockid_t clk_id = CLOCK_HIGHRES; |
1120 | const char *implementation = "clock_gettime(CLOCK_HIGHRES)"; |
1121 | #else |
1122 | const clockid_t clk_id = CLOCK_MONOTONIC; |
1123 | const char *implementation = "clock_gettime(CLOCK_MONOTONIC)"; |
1124 | #endif |
1125 | |
1126 | struct timespec ts; |
1127 | if (clock_gettime(clk_id, &ts) != 0) { Branch (1127:9): [True: 0, False: 20.3M]
|
1128 | if (raise_exc) { Branch (1128:13): [True: 0, False: 0]
|
1129 | PyErr_SetFromErrno(PyExc_OSError); |
1130 | return -1; |
1131 | } |
1132 | return -1; |
1133 | } |
1134 | |
1135 | if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) { Branch (1135:9): [True: 0, False: 20.3M]
|
1136 | return -1; |
1137 | } |
1138 | |
1139 | if (info) { Branch (1139:9): [True: 3.00k, False: 20.3M]
|
1140 | info->monotonic = 1; |
1141 | info->implementation = implementation; |
1142 | info->adjustable = 0; |
1143 | struct timespec res; |
1144 | if (clock_getres(clk_id, &res) != 0) { Branch (1144:13): [True: 0, False: 3.00k]
|
1145 | PyErr_SetFromErrno(PyExc_OSError); |
1146 | return -1; |
1147 | } |
1148 | info->resolution = res.tv_sec + res.tv_nsec * 1e-9; |
1149 | } |
1150 | #endif |
1151 | return 0; |
1152 | } |
1153 | |
1154 | |
1155 | _PyTime_t |
1156 | _PyTime_GetMonotonicClock(void) |
1157 | { |
1158 | _PyTime_t t; |
1159 | if (py_get_monotonic_clock(&t, NULL, 0) < 0) { Branch (1159:9): [True: 0, False: 16.3M]
|
1160 | // If mach_timebase_info(), clock_gettime() or gethrtime() fails: |
1161 | // silently ignore the failure and return 0. |
1162 | t = 0; |
1163 | } |
1164 | return t; |
1165 | } |
1166 | |
1167 | |
1168 | int |
1169 | _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) |
1170 | { |
1171 | return py_get_monotonic_clock(tp, info, 1); |
1172 | } |
1173 | |
1174 | |
1175 | #ifdef MS_WINDOWS |
1176 | static int |
1177 | py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise) |
1178 | { |
1179 | LONGLONG frequency; |
1180 | |
1181 | LARGE_INTEGER freq; |
1182 | // Since Windows XP, the function cannot fail. |
1183 | (void)QueryPerformanceFrequency(&freq); |
1184 | frequency = freq.QuadPart; |
1185 | |
1186 | // Since Windows XP, frequency cannot be zero. |
1187 | assert(frequency >= 1); |
1188 | |
1189 | /* Make also sure that (ticks * SEC_TO_NS) cannot overflow in |
1190 | _PyTime_MulDiv(), with ticks < frequency. |
1191 | |
1192 | Known QueryPerformanceFrequency() values: |
1193 | |
1194 | * 10,000,000 (10 MHz): 100 ns resolution |
1195 | * 3,579,545 Hz (3.6 MHz): 279 ns resolution |
1196 | |
1197 | None of these frequencies can overflow with 64-bit _PyTime_t, but |
1198 | check for integer overflow just in case. */ |
1199 | if (frequency > _PyTime_MAX / SEC_TO_NS) { |
1200 | if (raise) { |
1201 | PyErr_SetString(PyExc_OverflowError, |
1202 | "QueryPerformanceFrequency is too large"); |
1203 | } |
1204 | return -1; |
1205 | } |
1206 | |
1207 | *pfrequency = frequency; |
1208 | return 0; |
1209 | } |
1210 | |
1211 | |
1212 | static int |
1213 | py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise_exc) |
1214 | { |
1215 | assert(info == NULL || raise_exc); |
1216 | |
1217 | static LONGLONG frequency = 0; |
1218 | if (frequency == 0) { |
1219 | if (py_win_perf_counter_frequency(&frequency, raise_exc) < 0) { |
1220 | return -1; |
1221 | } |
1222 | } |
1223 | |
1224 | if (info) { |
1225 | info->implementation = "QueryPerformanceCounter()"; |
1226 | info->resolution = 1.0 / (double)frequency; |
1227 | info->monotonic = 1; |
1228 | info->adjustable = 0; |
1229 | } |
1230 | |
1231 | LARGE_INTEGER now; |
1232 | QueryPerformanceCounter(&now); |
1233 | LONGLONG ticksll = now.QuadPart; |
1234 | |
1235 | /* Make sure that casting LONGLONG to _PyTime_t cannot overflow, |
1236 | both types are signed */ |
1237 | _PyTime_t ticks; |
1238 | static_assert(sizeof(ticksll) <= sizeof(ticks), |
1239 | "LONGLONG is larger than _PyTime_t"); |
1240 | ticks = (_PyTime_t)ticksll; |
1241 | |
1242 | _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency); |
1243 | *tp = pytime_from_nanoseconds(ns); |
1244 | return 0; |
1245 | } |
1246 | #endif // MS_WINDOWS |
1247 | |
1248 | |
1249 | int |
1250 | _PyTime_GetPerfCounterWithInfo(_PyTime_t *t, _Py_clock_info_t *info) |
1251 | { |
1252 | #ifdef MS_WINDOWS |
1253 | return py_get_win_perf_counter(t, info, 1); |
1254 | #else |
1255 | return _PyTime_GetMonotonicClockWithInfo(t, info); |
1256 | #endif |
1257 | } |
1258 | |
1259 | |
1260 | _PyTime_t |
1261 | _PyTime_GetPerfCounter(void) |
1262 | { |
1263 | _PyTime_t t; |
1264 | int res; |
1265 | #ifdef MS_WINDOWS |
1266 | res = py_get_win_perf_counter(&t, NULL, 0); |
1267 | #else |
1268 | res = py_get_monotonic_clock(&t, NULL, 0); |
1269 | #endif |
1270 | if (res < 0) { Branch (1270:9): [True: 0, False: 802]
|
1271 | // If py_win_perf_counter_frequency() or py_get_monotonic_clock() |
1272 | // fails: silently ignore the failure and return 0. |
1273 | t = 0; |
1274 | } |
1275 | return t; |
1276 | } |
1277 | |
1278 | |
1279 | int |
1280 | _PyTime_localtime(time_t t, struct tm *tm) |
1281 | { |
1282 | #ifdef MS_WINDOWS |
1283 | int error; |
1284 | |
1285 | error = localtime_s(tm, &t); |
1286 | if (error != 0) { |
1287 | errno = error; |
1288 | PyErr_SetFromErrno(PyExc_OSError); |
1289 | return -1; |
1290 | } |
1291 | return 0; |
1292 | #else /* !MS_WINDOWS */ |
1293 | |
1294 | #if defined(_AIX) && (SIZEOF_TIME_T < 8) |
1295 | /* bpo-34373: AIX does not return NULL if t is too small or too large */ |
1296 | if (t < -2145916800 /* 1902-01-01 */ |
1297 | || t > 2145916800 /* 2038-01-01 */) { |
1298 | errno = EINVAL; |
1299 | PyErr_SetString(PyExc_OverflowError, |
1300 | "localtime argument out of range"); |
1301 | return -1; |
1302 | } |
1303 | #endif |
1304 | |
1305 | errno = 0; |
1306 | if (localtime_r(&t, tm) == NULL) { Branch (1306:9): [True: 3, False: 16.0k]
|
1307 | if (errno == 0) { Branch (1307:13): [True: 0, False: 3]
|
1308 | errno = EINVAL; |
1309 | } |
1310 | PyErr_SetFromErrno(PyExc_OSError); |
1311 | return -1; |
1312 | } |
1313 | return 0; |
1314 | #endif /* MS_WINDOWS */ |
1315 | } |
1316 | |
1317 | |
1318 | int |
1319 | _PyTime_gmtime(time_t t, struct tm *tm) |
1320 | { |
1321 | #ifdef MS_WINDOWS |
1322 | int error; |
1323 | |
1324 | error = gmtime_s(tm, &t); |
1325 | if (error != 0) { |
1326 | errno = error; |
1327 | PyErr_SetFromErrno(PyExc_OSError); |
1328 | return -1; |
1329 | } |
1330 | return 0; |
1331 | #else /* !MS_WINDOWS */ |
1332 | if (gmtime_r(&t, tm) == NULL) { Branch (1332:9): [True: 0, False: 2.97k]
|
1333 | #ifdef EINVAL |
1334 | if (errno == 0) { Branch (1334:13): [True: 0, False: 0]
|
1335 | errno = EINVAL; |
1336 | } |
1337 | #endif |
1338 | PyErr_SetFromErrno(PyExc_OSError); |
1339 | return -1; |
1340 | } |
1341 | return 0; |
1342 | #endif /* MS_WINDOWS */ |
1343 | } |
1344 | |
1345 | |
1346 | _PyTime_t |
1347 | _PyDeadline_Init(_PyTime_t timeout) |
1348 | { |
1349 | _PyTime_t now = _PyTime_GetMonotonicClock(); |
1350 | return _PyTime_Add(now, timeout); |
1351 | } |
1352 | |
1353 | |
1354 | _PyTime_t |
1355 | _PyDeadline_Get(_PyTime_t deadline) |
1356 | { |
1357 | _PyTime_t now = _PyTime_GetMonotonicClock(); |
1358 | return deadline - now; |
1359 | } |