Home | History | Annotate | Download | only in Python
      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
     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
     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 *
     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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    628 _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info)
    629 {
    630     return pygettimeofday(t, info, 1);
    631 }
    632 
    633 static int
    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
    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
    749 _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
    750 {
    751     return pymonotonic(tp, info, 1);
    752 }
    753 
    754 int
    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
    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
    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