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