1 #include "Python.h"
2 #ifdef MS_WINDOWS
3 #include <windows.h>
4 #endif
5 
6 #if defined(__APPLE__)
7 #include <mach/mach_time.h>   /* mach_absolute_time(), mach_timebase_info() */
8 #endif
9 
10 #define _PyTime_check_mul_overflow(a, b) \
11     (assert(b > 0), \
12      (_PyTime_t)(a) < _PyTime_MIN / (_PyTime_t)(b) \
13      || _PyTime_MAX / (_PyTime_t)(b) < (_PyTime_t)(a))
14 
15 /* To millisecond (10^-3) */
16 #define SEC_TO_MS 1000
17 
18 /* To microseconds (10^-6) */
19 #define MS_TO_US 1000
20 #define SEC_TO_US (SEC_TO_MS * MS_TO_US)
21 
22 /* To nanoseconds (10^-9) */
23 #define US_TO_NS 1000
24 #define MS_TO_NS (MS_TO_US * US_TO_NS)
25 #define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
26 
27 /* Conversion from nanoseconds */
28 #define NS_TO_MS (1000 * 1000)
29 #define NS_TO_US (1000)
30 
31 static void
error_time_t_overflow(void)32 error_time_t_overflow(void)
33 {
34     PyErr_SetString(PyExc_OverflowError,
35                     "timestamp out of range for platform time_t");
36 }
37 
38 time_t
_PyLong_AsTime_t(PyObject * obj)39 _PyLong_AsTime_t(PyObject *obj)
40 {
41 #if SIZEOF_TIME_T == SIZEOF_LONG_LONG
42     long long val;
43     val = PyLong_AsLongLong(obj);
44 #else
45     long val;
46     Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
47     val = PyLong_AsLong(obj);
48 #endif
49     if (val == -1 && PyErr_Occurred()) {
50         if (PyErr_ExceptionMatches(PyExc_OverflowError))
51             error_time_t_overflow();
52         return -1;
53     }
54     return (time_t)val;
55 }
56 
57 PyObject *
_PyLong_FromTime_t(time_t t)58 _PyLong_FromTime_t(time_t t)
59 {
60 #if SIZEOF_TIME_T == SIZEOF_LONG_LONG
61     return PyLong_FromLongLong((long long)t);
62 #else
63     Py_BUILD_ASSERT(sizeof(time_t) <= sizeof(long));
64     return PyLong_FromLong((long)t);
65 #endif
66 }
67 
68 /* Round to nearest with ties going to nearest even integer
69    (_PyTime_ROUND_HALF_EVEN) */
70 static double
_PyTime_RoundHalfEven(double x)71 _PyTime_RoundHalfEven(double x)
72 {
73     double rounded = round(x);
74     if (fabs(x-rounded) == 0.5)
75         /* halfway case: round to even */
76         rounded = 2.0*round(x/2.0);
77     return rounded;
78 }
79 
80 static double
_PyTime_Round(double x,_PyTime_round_t round)81 _PyTime_Round(double x, _PyTime_round_t round)
82 {
83     /* volatile avoids optimization changing how numbers are rounded */
84     volatile double d;
85 
86     d = x;
87     if (round == _PyTime_ROUND_HALF_EVEN)
88         d = _PyTime_RoundHalfEven(d);
89     else if (round == _PyTime_ROUND_CEILING)
90         d = ceil(d);
91     else
92         d = floor(d);
93     return d;
94 }
95 
96 static int
_PyTime_DoubleToDenominator(double d,time_t * sec,long * numerator,double denominator,_PyTime_round_t round)97 _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator,
98                             double denominator, _PyTime_round_t round)
99 {
100     double intpart, err;
101     /* volatile avoids optimization changing how numbers are rounded */
102     volatile double floatpart;
103 
104     floatpart = modf(d, &intpart);
105 
106     floatpart *= denominator;
107     floatpart = _PyTime_Round(floatpart, round);
108     if (floatpart >= denominator) {
109         floatpart -= denominator;
110         intpart += 1.0;
111     }
112     else if (floatpart < 0) {
113         floatpart += denominator;
114         intpart -= 1.0;
115     }
116     assert(0.0 <= floatpart && floatpart < denominator);
117 
118     *sec = (time_t)intpart;
119     *numerator = (long)floatpart;
120 
121     err = intpart - (double)*sec;
122     if (err <= -1.0 || err >= 1.0) {
123         error_time_t_overflow();
124         return -1;
125     }
126     return 0;
127 }
128 
129 static int
_PyTime_ObjectToDenominator(PyObject * obj,time_t * sec,long * numerator,double denominator,_PyTime_round_t round)130 _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
131                             double denominator, _PyTime_round_t round)
132 {
133     assert(denominator <= (double)LONG_MAX);
134 
135     if (PyFloat_Check(obj)) {
136         double d = PyFloat_AsDouble(obj);
137         return _PyTime_DoubleToDenominator(d, sec, numerator,
138                                            denominator, round);
139     }
140     else {
141         *sec = _PyLong_AsTime_t(obj);
142         *numerator = 0;
143         if (*sec == (time_t)-1 && PyErr_Occurred())
144             return -1;
145         return 0;
146     }
147 }
148 
149 int
_PyTime_ObjectToTime_t(PyObject * obj,time_t * sec,_PyTime_round_t round)150 _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
151 {
152     if (PyFloat_Check(obj)) {
153         double intpart, err;
154         /* volatile avoids optimization changing how numbers are rounded */
155         volatile double d;
156 
157         d = PyFloat_AsDouble(obj);
158         d = _PyTime_Round(d, round);
159         (void)modf(d, &intpart);
160 
161         *sec = (time_t)intpart;
162         err = intpart - (double)*sec;
163         if (err <= -1.0 || err >= 1.0) {
164             error_time_t_overflow();
165             return -1;
166         }
167         return 0;
168     }
169     else {
170         *sec = _PyLong_AsTime_t(obj);
171         if (*sec == (time_t)-1 && PyErr_Occurred())
172             return -1;
173         return 0;
174     }
175 }
176 
177 int
_PyTime_ObjectToTimespec(PyObject * obj,time_t * sec,long * nsec,_PyTime_round_t round)178 _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
179                          _PyTime_round_t round)
180 {
181     int res;
182     res = _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9, round);
183     assert(0 <= *nsec && *nsec < SEC_TO_NS);
184     return res;
185 }
186 
187 int
_PyTime_ObjectToTimeval(PyObject * obj,time_t * sec,long * usec,_PyTime_round_t round)188 _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
189                         _PyTime_round_t round)
190 {
191     int res;
192     res = _PyTime_ObjectToDenominator(obj, sec, usec, 1e6, round);
193     assert(0 <= *usec && *usec < SEC_TO_US);
194     return res;
195 }
196 
197 static void
_PyTime_overflow(void)198 _PyTime_overflow(void)
199 {
200     PyErr_SetString(PyExc_OverflowError,
201                     "timestamp too large to convert to C _PyTime_t");
202 }
203 
204 _PyTime_t
_PyTime_FromSeconds(int seconds)205 _PyTime_FromSeconds(int seconds)
206 {
207     _PyTime_t t;
208     t = (_PyTime_t)seconds;
209     /* ensure that integer overflow cannot happen, int type should have 32
210        bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30
211        bits). */
212     Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS);
213     Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS);
214     assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS)
215            || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS));
216     t *= SEC_TO_NS;
217     return t;
218 }
219 
220 _PyTime_t
_PyTime_FromNanoseconds(long long ns)221 _PyTime_FromNanoseconds(long long ns)
222 {
223     _PyTime_t t;
224     Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
225     t = Py_SAFE_DOWNCAST(ns, long long, _PyTime_t);
226     return t;
227 }
228 
229 #ifdef HAVE_CLOCK_GETTIME
230 static int
_PyTime_FromTimespec(_PyTime_t * tp,struct timespec * ts,int raise)231 _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise)
232 {
233     _PyTime_t t;
234     int res = 0;
235 
236     Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t));
237     t = (_PyTime_t)ts->tv_sec;
238 
239     if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
240         if (raise)
241             _PyTime_overflow();
242         res = -1;
243     }
244     t = t * SEC_TO_NS;
245 
246     t += ts->tv_nsec;
247 
248     *tp = t;
249     return res;
250 }
251 #elif !defined(MS_WINDOWS)
252 static int
_PyTime_FromTimeval(_PyTime_t * tp,struct timeval * tv,int raise)253 _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise)
254 {
255     _PyTime_t t;
256     int res = 0;
257 
258     Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t));
259     t = (_PyTime_t)tv->tv_sec;
260 
261     if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) {
262         if (raise)
263             _PyTime_overflow();
264         res = -1;
265     }
266     t = t * SEC_TO_NS;
267 
268     t += (_PyTime_t)tv->tv_usec * US_TO_NS;
269 
270     *tp = t;
271     return res;
272 }
273 #endif
274 
275 static int
_PyTime_FromFloatObject(_PyTime_t * t,double value,_PyTime_round_t round,long unit_to_ns)276 _PyTime_FromFloatObject(_PyTime_t *t, double value, _PyTime_round_t round,
277                         long unit_to_ns)
278 {
279     double err;
280     /* volatile avoids optimization changing how numbers are rounded */
281     volatile double d;
282 
283     /* convert to a number of nanoseconds */
284     d = value;
285     d *= (double)unit_to_ns;
286     d = _PyTime_Round(d, round);
287 
288     *t = (_PyTime_t)d;
289     err = d - (double)*t;
290     if (fabs(err) >= 1.0) {
291         _PyTime_overflow();
292         return -1;
293     }
294     return 0;
295 }
296 
297 static int
_PyTime_FromObject(_PyTime_t * t,PyObject * obj,_PyTime_round_t round,long unit_to_ns)298 _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round,
299                    long unit_to_ns)
300 {
301     if (PyFloat_Check(obj)) {
302         double d;
303         d = PyFloat_AsDouble(obj);
304         return _PyTime_FromFloatObject(t, d, round, unit_to_ns);
305     }
306     else {
307         long long sec;
308         Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t));
309 
310         sec = PyLong_AsLongLong(obj);
311         if (sec == -1 && PyErr_Occurred()) {
312             if (PyErr_ExceptionMatches(PyExc_OverflowError))
313                 _PyTime_overflow();
314             return -1;
315         }
316 
317         if (_PyTime_check_mul_overflow(sec, unit_to_ns)) {
318             _PyTime_overflow();
319             return -1;
320         }
321         *t = sec * unit_to_ns;
322         return 0;
323     }
324 }
325 
326 int
_PyTime_FromSecondsObject(_PyTime_t * t,PyObject * obj,_PyTime_round_t round)327 _PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
328 {
329     return _PyTime_FromObject(t, obj, round, SEC_TO_NS);
330 }
331 
332 int
_PyTime_FromMillisecondsObject(_PyTime_t * t,PyObject * obj,_PyTime_round_t round)333 _PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round)
334 {
335     return _PyTime_FromObject(t, obj, round, MS_TO_NS);
336 }
337 
338 double
_PyTime_AsSecondsDouble(_PyTime_t t)339 _PyTime_AsSecondsDouble(_PyTime_t t)
340 {
341     /* volatile avoids optimization changing how numbers are rounded */
342     volatile double d;
343 
344     if (t % SEC_TO_NS == 0) {
345         _PyTime_t secs;
346         /* Divide using integers to avoid rounding issues on the integer part.
347            1e-9 cannot be stored exactly in IEEE 64-bit. */
348         secs = t / SEC_TO_NS;
349         d = (double)secs;
350     }
351     else {
352         d = (double)t;
353         d /= 1e9;
354     }
355     return d;
356 }
357 
358 PyObject *
_PyTime_AsNanosecondsObject(_PyTime_t t)359 _PyTime_AsNanosecondsObject(_PyTime_t t)
360 {
361     Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t));
362     return PyLong_FromLongLong((long long)t);
363 }
364 
365 static _PyTime_t
_PyTime_Divide(const _PyTime_t t,const _PyTime_t k,const _PyTime_round_t round)366 _PyTime_Divide(const _PyTime_t t, const _PyTime_t k,
367                const _PyTime_round_t round)
368 {
369     assert(k > 1);
370     if (round == _PyTime_ROUND_HALF_EVEN) {
371         _PyTime_t x, r, abs_r;
372         x = t / k;
373         r = t % k;
374         abs_r = Py_ABS(r);
375         if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
376             if (t >= 0)
377                 x++;
378             else
379                 x--;
380         }
381         return x;
382     }
383     else if (round == _PyTime_ROUND_CEILING) {
384         if (t >= 0)
385             return (t + k - 1) / k;
386         else
387             return t / k;
388     }
389     else {
390         if (t >= 0)
391             return t / k;
392         else
393             return (t - (k - 1)) / k;
394     }
395 }
396 
397 _PyTime_t
_PyTime_AsMilliseconds(_PyTime_t t,_PyTime_round_t round)398 _PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round)
399 {
400     return _PyTime_Divide(t, NS_TO_MS, round);
401 }
402 
403 _PyTime_t
_PyTime_AsMicroseconds(_PyTime_t t,_PyTime_round_t round)404 _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round)
405 {
406     return _PyTime_Divide(t, NS_TO_US, round);
407 }
408 
409 static int
_PyTime_AsTimeval_impl(_PyTime_t t,_PyTime_t * p_secs,int * p_us,_PyTime_round_t round)410 _PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us,
411                        _PyTime_round_t round)
412 {
413     _PyTime_t secs, ns;
414     int usec;
415     int res = 0;
416 
417     secs = t / SEC_TO_NS;
418     ns = t % SEC_TO_NS;
419 
420     usec = (int)_PyTime_Divide(ns, US_TO_NS, round);
421     if (usec < 0) {
422         usec += SEC_TO_US;
423         if (secs != _PyTime_MIN)
424             secs -= 1;
425         else
426             res = -1;
427     }
428     else if (usec >= SEC_TO_US) {
429         usec -= SEC_TO_US;
430         if (secs != _PyTime_MAX)
431             secs += 1;
432         else
433             res = -1;
434     }
435     assert(0 <= usec && usec < SEC_TO_US);
436 
437     *p_secs = secs;
438     *p_us = usec;
439 
440     return res;
441 }
442 
443 static int
_PyTime_AsTimevalStruct_impl(_PyTime_t t,struct timeval * tv,_PyTime_round_t round,int raise)444 _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv,
445                              _PyTime_round_t round, int raise)
446 {
447     _PyTime_t secs, secs2;
448     int us;
449     int res;
450 
451     res = _PyTime_AsTimeval_impl(t, &secs, &us, round);
452 
453 #ifdef MS_WINDOWS
454     tv->tv_sec = (long)secs;
455 #else
456     tv->tv_sec = secs;
457 #endif
458     tv->tv_usec = us;
459 
460     secs2 = (_PyTime_t)tv->tv_sec;
461     if (res < 0 || secs2 != secs) {
462         if (raise)
463             error_time_t_overflow();
464         return -1;
465     }
466     return 0;
467 }
468 
469 int
_PyTime_AsTimeval(_PyTime_t t,struct timeval * tv,_PyTime_round_t round)470 _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
471 {
472     return _PyTime_AsTimevalStruct_impl(t, tv, round, 1);
473 }
474 
475 int
_PyTime_AsTimeval_noraise(_PyTime_t t,struct timeval * tv,_PyTime_round_t round)476 _PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round)
477 {
478     return _PyTime_AsTimevalStruct_impl(t, tv, round, 0);
479 }
480 
481 int
_PyTime_AsTimevalTime_t(_PyTime_t t,time_t * p_secs,int * us,_PyTime_round_t round)482 _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us,
483                         _PyTime_round_t round)
484 {
485     _PyTime_t secs;
486     int res;
487 
488     res = _PyTime_AsTimeval_impl(t, &secs, us, round);
489 
490     *p_secs = secs;
491 
492     if (res < 0 || (_PyTime_t)*p_secs != secs) {
493         error_time_t_overflow();
494         return -1;
495     }
496     return 0;
497 }
498 
499 
500 #if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
501 int
_PyTime_AsTimespec(_PyTime_t t,struct timespec * ts)502 _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts)
503 {
504     _PyTime_t secs, nsec;
505 
506     secs = t / SEC_TO_NS;
507     nsec = t % SEC_TO_NS;
508     if (nsec < 0) {
509         nsec += SEC_TO_NS;
510         secs -= 1;
511     }
512     ts->tv_sec = (time_t)secs;
513     assert(0 <= nsec && nsec < SEC_TO_NS);
514     ts->tv_nsec = nsec;
515 
516     if ((_PyTime_t)ts->tv_sec != secs) {
517         error_time_t_overflow();
518         return -1;
519     }
520     return 0;
521 }
522 #endif
523 
524 static int
pygettimeofday(_PyTime_t * tp,_Py_clock_info_t * info,int raise)525 pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
526 {
527 #ifdef MS_WINDOWS
528     FILETIME system_time;
529     ULARGE_INTEGER large;
530 
531     assert(info == NULL || raise);
532 
533     GetSystemTimeAsFileTime(&system_time);
534     large.u.LowPart = system_time.dwLowDateTime;
535     large.u.HighPart = system_time.dwHighDateTime;
536     /* 11,644,473,600,000,000,000: number of nanoseconds between
537        the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
538        days). */
539     *tp = large.QuadPart * 100 - 11644473600000000000;
540     if (info) {
541         DWORD timeAdjustment, timeIncrement;
542         BOOL isTimeAdjustmentDisabled, ok;
543 
544         info->implementation = "GetSystemTimeAsFileTime()";
545         info->monotonic = 0;
546         ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
547                                      &isTimeAdjustmentDisabled);
548         if (!ok) {
549             PyErr_SetFromWindowsErr(0);
550             return -1;
551         }
552         info->resolution = timeIncrement * 1e-7;
553         info->adjustable = 1;
554     }
555 
556 #else   /* MS_WINDOWS */
557     int err;
558 #ifdef HAVE_CLOCK_GETTIME
559     struct timespec ts;
560 #else
561     struct timeval tv;
562 #endif
563 
564     assert(info == NULL || raise);
565 
566 #ifdef HAVE_CLOCK_GETTIME
567     err = clock_gettime(CLOCK_REALTIME, &ts);
568     if (err) {
569         if (raise)
570             PyErr_SetFromErrno(PyExc_OSError);
571         return -1;
572     }
573     if (_PyTime_FromTimespec(tp, &ts, raise) < 0)
574         return -1;
575 
576     if (info) {
577         struct timespec res;
578         info->implementation = "clock_gettime(CLOCK_REALTIME)";
579         info->monotonic = 0;
580         info->adjustable = 1;
581         if (clock_getres(CLOCK_REALTIME, &res) == 0)
582             info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
583         else
584             info->resolution = 1e-9;
585     }
586 #else   /* HAVE_CLOCK_GETTIME */
587 
588      /* test gettimeofday() */
589 #ifdef GETTIMEOFDAY_NO_TZ
590     err = gettimeofday(&tv);
591 #else
592     err = gettimeofday(&tv, (struct timezone *)NULL);
593 #endif
594     if (err) {
595         if (raise)
596             PyErr_SetFromErrno(PyExc_OSError);
597         return -1;
598     }
599     if (_PyTime_FromTimeval(tp, &tv, raise) < 0)
600         return -1;
601 
602     if (info) {
603         info->implementation = "gettimeofday()";
604         info->resolution = 1e-6;
605         info->monotonic = 0;
606         info->adjustable = 1;
607     }
608 #endif   /* !HAVE_CLOCK_GETTIME */
609 #endif   /* !MS_WINDOWS */
610     return 0;
611 }
612 
613 _PyTime_t
_PyTime_GetSystemClock(void)614 _PyTime_GetSystemClock(void)
615 {
616     _PyTime_t t;
617     if (pygettimeofday(&t, NULL, 0) < 0) {
618         /* should not happen, _PyTime_Init() checked the clock at startup */
619         assert(0);
620 
621         /* use a fixed value instead of a random value from the stack */
622         t = 0;
623     }
624     return t;
625 }
626 
627 int
_PyTime_GetSystemClockWithInfo(_PyTime_t * t,_Py_clock_info_t * info)628 _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
629 {
630     return pygettimeofday(t, info, 1);
631 }
632 
633 static int
pymonotonic(_PyTime_t * tp,_Py_clock_info_t * info,int raise)634 pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise)
635 {
636 #if defined(MS_WINDOWS)
637     ULONGLONG ticks;
638     _PyTime_t t;
639 
640     assert(info == NULL || raise);
641 
642     ticks = GetTickCount64();
643     Py_BUILD_ASSERT(sizeof(ticks) <= sizeof(_PyTime_t));
644     t = (_PyTime_t)ticks;
645 
646     if (_PyTime_check_mul_overflow(t, MS_TO_NS)) {
647         if (raise) {
648             _PyTime_overflow();
649             return -1;
650         }
651         /* Hello, time traveler! */
652         assert(0);
653     }
654     *tp = t * MS_TO_NS;
655 
656     if (info) {
657         DWORD timeAdjustment, timeIncrement;
658         BOOL isTimeAdjustmentDisabled, ok;
659         info->implementation = "GetTickCount64()";
660         info->monotonic = 1;
661         ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement,
662                                      &isTimeAdjustmentDisabled);
663         if (!ok) {
664             PyErr_SetFromWindowsErr(0);
665             return -1;
666         }
667         info->resolution = timeIncrement * 1e-7;
668         info->adjustable = 0;
669     }
670 
671 #elif defined(__APPLE__)
672     static mach_timebase_info_data_t timebase;
673     uint64_t time;
674 
675     if (timebase.denom == 0) {
676         /* According to the Technical Q&A QA1398, mach_timebase_info() cannot
677            fail: https://developer.apple.com/library/mac/#qa/qa1398/ */
678         (void)mach_timebase_info(&timebase);
679     }
680 
681     time = mach_absolute_time();
682 
683     /* apply timebase factor */
684     time *= timebase.numer;
685     time /= timebase.denom;
686 
687     *tp = time;
688 
689     if (info) {
690         info->implementation = "mach_absolute_time()";
691         info->resolution = (double)timebase.numer / timebase.denom * 1e-9;
692         info->monotonic = 1;
693         info->adjustable = 0;
694     }
695 
696 #else
697     struct timespec ts;
698 #ifdef CLOCK_HIGHRES
699     const clockid_t clk_id = CLOCK_HIGHRES;
700     const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
701 #else
702     const clockid_t clk_id = CLOCK_MONOTONIC;
703     const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
704 #endif
705 
706     assert(info == NULL || raise);
707 
708     if (clock_gettime(clk_id, &ts) != 0) {
709         if (raise) {
710             PyErr_SetFromErrno(PyExc_OSError);
711             return -1;
712         }
713         return -1;
714     }
715 
716     if (info) {
717         struct timespec res;
718         info->monotonic = 1;
719         info->implementation = implementation;
720         info->adjustable = 0;
721         if (clock_getres(clk_id, &res) != 0) {
722             PyErr_SetFromErrno(PyExc_OSError);
723             return -1;
724         }
725         info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
726     }
727     if (_PyTime_FromTimespec(tp, &ts, raise) < 0)
728         return -1;
729 #endif
730     return 0;
731 }
732 
733 _PyTime_t
_PyTime_GetMonotonicClock(void)734 _PyTime_GetMonotonicClock(void)
735 {
736     _PyTime_t t;
737     if (pymonotonic(&t, NULL, 0) < 0) {
738         /* should not happen, _PyTime_Init() checked that monotonic clock at
739            startup */
740         assert(0);
741 
742         /* use a fixed value instead of a random value from the stack */
743         t = 0;
744     }
745     return t;
746 }
747 
748 int
_PyTime_GetMonotonicClockWithInfo(_PyTime_t * tp,_Py_clock_info_t * info)749 _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
750 {
751     return pymonotonic(tp, info, 1);
752 }
753 
754 int
_PyTime_Init(void)755 _PyTime_Init(void)
756 {
757     _PyTime_t t;
758 
759     /* ensure that the system clock works */
760     if (_PyTime_GetSystemClockWithInfo(&t, NULL) < 0)
761         return -1;
762 
763     /* ensure that the operating system provides a monotonic clock */
764     if (_PyTime_GetMonotonicClockWithInfo(&t, NULL) < 0)
765         return -1;
766 
767     return 0;
768 }
769 
770 int
_PyTime_localtime(time_t t,struct tm * tm)771 _PyTime_localtime(time_t t, struct tm *tm)
772 {
773 #ifdef MS_WINDOWS
774     int error;
775 
776     error = localtime_s(tm, &t);
777     if (error != 0) {
778         errno = error;
779         PyErr_SetFromErrno(PyExc_OSError);
780         return -1;
781     }
782     return 0;
783 #else /* !MS_WINDOWS */
784     if (localtime_r(&t, tm) == NULL) {
785 #ifdef EINVAL
786         if (errno == 0)
787             errno = EINVAL;
788 #endif
789         PyErr_SetFromErrno(PyExc_OSError);
790         return -1;
791     }
792     return 0;
793 #endif /* MS_WINDOWS */
794 }
795 
796 int
_PyTime_gmtime(time_t t,struct tm * tm)797 _PyTime_gmtime(time_t t, struct tm *tm)
798 {
799 #ifdef MS_WINDOWS
800     int error;
801 
802     error = gmtime_s(tm, &t);
803     if (error != 0) {
804         errno = error;
805         PyErr_SetFromErrno(PyExc_OSError);
806         return -1;
807     }
808     return 0;
809 #else /* !MS_WINDOWS */
810     if (gmtime_r(&t, tm) == NULL) {
811 #ifdef EINVAL
812         if (errno == 0)
813             errno = EINVAL;
814 #endif
815         PyErr_SetFromErrno(PyExc_OSError);
816         return -1;
817     }
818     return 0;
819 #endif /* MS_WINDOWS */
820 }
821