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