diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h index 56607d199ed..b0453884398 100644 --- a/Include/cpython/pytime.h +++ b/Include/cpython/pytime.h @@ -111,6 +111,9 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t, PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round); +/* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); + /* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int object. */ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index b1e64f19f2d..51323f03e23 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4623,11 +4623,10 @@ static PyObject * test_pytime_fromseconds(PyObject *self, PyObject *args) { int seconds; - _PyTime_t ts; - - if (!PyArg_ParseTuple(args, "i", &seconds)) + if (!PyArg_ParseTuple(args, "i", &seconds)) { return NULL; - ts = _PyTime_FromSeconds(seconds); + } + _PyTime_t ts = _PyTime_FromSeconds(seconds); return _PyTime_AsNanosecondsObject(ts); } @@ -4636,14 +4635,16 @@ test_pytime_fromsecondsobject(PyObject *self, PyObject *args) { PyObject *obj; int round; + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { + return NULL; + } + if (check_time_rounding(round) < 0) { + return NULL; + } _PyTime_t ts; - - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) - return NULL; - if (check_time_rounding(round) < 0) - return NULL; - if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) + if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) { return NULL; + } return _PyTime_AsNanosecondsObject(ts); } @@ -4651,16 +4652,14 @@ static PyObject * test_pytime_assecondsdouble(PyObject *self, PyObject *args) { PyObject *obj; - _PyTime_t ts; - double d; - if (!PyArg_ParseTuple(args, "O", &obj)) { return NULL; } + _PyTime_t ts; if (_PyTime_FromNanosecondsObject(&ts, obj) < 0) { return NULL; } - d = _PyTime_AsSecondsDouble(ts); + double d = _PyTime_AsSecondsDouble(ts); return PyFloat_FromDouble(d); } @@ -4669,23 +4668,22 @@ test_PyTime_AsTimeval(PyObject *self, PyObject *args) { PyObject *obj; int round; - _PyTime_t t; - struct timeval tv; - PyObject *seconds; - - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { return NULL; + } if (check_time_rounding(round) < 0) { return NULL; } + _PyTime_t t; if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { return NULL; } + struct timeval tv; if (_PyTime_AsTimeval(t, &tv, round) < 0) { return NULL; } - seconds = PyLong_FromLongLong(tv.tv_sec); + PyObject *seconds = PyLong_FromLongLong(tv.tv_sec); if (seconds == NULL) { return NULL; } @@ -4697,15 +4695,14 @@ static PyObject * test_PyTime_AsTimespec(PyObject *self, PyObject *args) { PyObject *obj; - _PyTime_t t; - struct timespec ts; - if (!PyArg_ParseTuple(args, "O", &obj)) { return NULL; } + _PyTime_t t; if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { return NULL; } + struct timespec ts; if (_PyTime_AsTimespec(t, &ts) == -1) { return NULL; } @@ -4718,21 +4715,19 @@ test_PyTime_AsMilliseconds(PyObject *self, PyObject *args) { PyObject *obj; int round; - _PyTime_t t, ms; - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { return NULL; } + _PyTime_t t; if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { return NULL; } if (check_time_rounding(round) < 0) { return NULL; } - ms = _PyTime_AsMilliseconds(t, round); - /* This conversion rely on the fact that _PyTime_t is a number of - nanoseconds */ - return _PyTime_AsNanosecondsObject(ms); + _PyTime_t ms = _PyTime_AsMilliseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(ms); + return _PyTime_AsNanosecondsObject(ns); } static PyObject * @@ -4740,20 +4735,19 @@ test_PyTime_AsMicroseconds(PyObject *self, PyObject *args) { PyObject *obj; int round; - _PyTime_t t, ms; - - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { return NULL; + } + _PyTime_t t; if (_PyTime_FromNanosecondsObject(&t, obj) < 0) { return NULL; } if (check_time_rounding(round) < 0) { return NULL; } - ms = _PyTime_AsMicroseconds(t, round); - /* This conversion rely on the fact that _PyTime_t is a number of - nanoseconds */ - return _PyTime_AsNanosecondsObject(ms); + _PyTime_t us = _PyTime_AsMicroseconds(t, round); + _PyTime_t ns = _PyTime_FromNanoseconds(us); + return _PyTime_AsNanosecondsObject(ns); } static PyObject* diff --git a/Modules/timemodule.c b/Modules/timemodule.c index cf58a18caf1..52c61154f3a 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -128,12 +128,11 @@ static int _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { static int initialized = 0; - clock_t ticks; if (!initialized) { initialized = 1; - /* must sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC) + /* Make sure that _PyTime_MulDiv(ticks, SEC_TO_NS, CLOCKS_PER_SEC) above cannot overflow */ if ((_PyTime_t)CLOCKS_PER_SEC > _PyTime_MAX / SEC_TO_NS) { PyErr_SetString(PyExc_OverflowError, @@ -149,14 +148,15 @@ _PyTime_GetClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) info->adjustable = 0; } - ticks = clock(); + clock_t ticks = clock(); if (ticks == (clock_t)-1) { PyErr_SetString(PyExc_RuntimeError, "the processor time used is not available " "or its value cannot be represented"); return -1; } - *tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC); + _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)CLOCKS_PER_SEC); + *tp = _PyTime_FromNanoseconds(ns); return 0; } #endif /* HAVE_CLOCK */ @@ -1325,10 +1325,10 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) info->resolution = 1.0 / (double)ticks_per_second; } - _PyTime_t total; - total = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second); - total += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second); - *tp = total; + _PyTime_t ns; + ns = _PyTime_MulDiv(t.tms_utime, SEC_TO_NS, ticks_per_second); + ns += _PyTime_MulDiv(t.tms_stime, SEC_TO_NS, ticks_per_second); + *tp = _PyTime_FromNanoseconds(ns); return 0; } } diff --git a/Python/pytime.c b/Python/pytime.c index 1ef99aee748..8035a5f8a28 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -34,21 +34,39 @@ #define NS_TO_MS (1000 * 1000) #define NS_TO_US (1000) + static void -error_time_t_overflow(void) +pytime_time_t_overflow(void) { PyErr_SetString(PyExc_OverflowError, "timestamp out of range for platform time_t"); } + static void -_PyTime_overflow(void) +pytime_overflow(void) { PyErr_SetString(PyExc_OverflowError, "timestamp too large to convert to C _PyTime_t"); } +static inline _PyTime_t +pytime_from_nanoseconds(_PyTime_t t) +{ + // _PyTime_t is a number of nanoseconds + return t; +} + + +static inline _PyTime_t +pytime_as_nanoseconds(_PyTime_t t) +{ + // _PyTime_t is a number of nanoseconds + return t; +} + + _PyTime_t _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) { @@ -80,13 +98,14 @@ _PyLong_AsTime_t(PyObject *obj) #endif if (val == -1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - error_time_t_overflow(); + pytime_time_t_overflow(); } return -1; } return (time_t)val; } + PyObject * _PyLong_FromTime_t(time_t t) { @@ -98,28 +117,30 @@ _PyLong_FromTime_t(time_t t) #endif } + /* Round to nearest with ties going to nearest even integer (_PyTime_ROUND_HALF_EVEN) */ static double -_PyTime_RoundHalfEven(double x) +pytime_round_half_even(double x) { double rounded = round(x); if (fabs(x-rounded) == 0.5) { /* halfway case: round to even */ - rounded = 2.0*round(x/2.0); + rounded = 2.0 * round(x / 2.0); } return rounded; } + static double -_PyTime_Round(double x, _PyTime_round_t round) +pytime_round(double x, _PyTime_round_t round) { /* volatile avoids optimization changing how numbers are rounded */ volatile double d; d = x; if (round == _PyTime_ROUND_HALF_EVEN) { - d = _PyTime_RoundHalfEven(d); + d = pytime_round_half_even(d); } else if (round == _PyTime_ROUND_CEILING) { d = ceil(d); @@ -134,9 +155,10 @@ _PyTime_Round(double x, _PyTime_round_t round) return d; } + static int -_PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, - long idenominator, _PyTime_round_t round) +pytime_double_to_denominator(double d, time_t *sec, long *numerator, + long idenominator, _PyTime_round_t round) { double denominator = (double)idenominator; double intpart; @@ -146,7 +168,7 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, floatpart = modf(d, &intpart); floatpart *= denominator; - floatpart = _PyTime_Round(floatpart, round); + floatpart = pytime_round(floatpart, round); if (floatpart >= denominator) { floatpart -= denominator; intpart += 1.0; @@ -158,7 +180,7 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, assert(0.0 <= floatpart && floatpart < denominator); if (!_Py_InIntegralTypeRange(time_t, intpart)) { - error_time_t_overflow(); + pytime_time_t_overflow(); return -1; } *sec = (time_t)intpart; @@ -167,9 +189,10 @@ _PyTime_DoubleToDenominator(double d, time_t *sec, long *numerator, return 0; } + static int -_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, - long denominator, _PyTime_round_t round) +pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator, + long denominator, _PyTime_round_t round) { assert(denominator >= 1); @@ -180,8 +203,8 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); return -1; } - return _PyTime_DoubleToDenominator(d, sec, numerator, - denominator, round); + return pytime_double_to_denominator(d, sec, numerator, + denominator, round); } else { *sec = _PyLong_AsTime_t(obj); @@ -193,6 +216,7 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, } } + int _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) { @@ -207,11 +231,11 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) return -1; } - d = _PyTime_Round(d, round); + d = pytime_round(d, round); (void)modf(d, &intpart); if (!_Py_InIntegralTypeRange(time_t, intpart)) { - error_time_t_overflow(); + pytime_time_t_overflow(); return -1; } *sec = (time_t)intpart; @@ -226,49 +250,50 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round) } } + int _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec, _PyTime_round_t round) { - return _PyTime_ObjectToDenominator(obj, sec, nsec, SEC_TO_NS, round); + return pytime_object_to_denominator(obj, sec, nsec, SEC_TO_NS, round); } + int _PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec, _PyTime_round_t round) { - return _PyTime_ObjectToDenominator(obj, sec, usec, SEC_TO_US, round); + return pytime_object_to_denominator(obj, sec, usec, SEC_TO_US, round); } + _PyTime_t _PyTime_FromSeconds(int seconds) { - _PyTime_t t; /* ensure that integer overflow cannot happen, int type should have 32 bits, whereas _PyTime_t type has at least 64 bits (SEC_TO_MS takes 30 bits). */ Py_BUILD_ASSERT(INT_MAX <= _PyTime_MAX / SEC_TO_NS); Py_BUILD_ASSERT(INT_MIN >= _PyTime_MIN / SEC_TO_NS); - t = (_PyTime_t)seconds; + _PyTime_t t = (_PyTime_t)seconds; assert((t >= 0 && t <= _PyTime_MAX / SEC_TO_NS) || (t < 0 && t >= _PyTime_MIN / SEC_TO_NS)); t *= SEC_TO_NS; - return t; + return pytime_from_nanoseconds(t); } + _PyTime_t _PyTime_FromNanoseconds(_PyTime_t ns) { - /* _PyTime_t already uses nanosecond resolution, no conversion needed */ - return ns; + return pytime_from_nanoseconds(ns); } + int _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) { - long long nsec; - _PyTime_t t; if (!PyLong_Check(obj)) { PyErr_Format(PyExc_TypeError, "expect int, got %s", @@ -277,25 +302,25 @@ _PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) } Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t)); - nsec = PyLong_AsLongLong(obj); + long long nsec = PyLong_AsLongLong(obj); if (nsec == -1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - _PyTime_overflow(); + pytime_overflow(); } return -1; } - /* _PyTime_t already uses nanosecond resolution, no conversion needed */ - t = (_PyTime_t)nsec; - *tp = t; + _PyTime_t t = (_PyTime_t)nsec; + *tp = pytime_from_nanoseconds(t); return 0; } + #ifdef HAVE_CLOCK_GETTIME static int pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise) { - _PyTime_t t, nsec; + _PyTime_t t, tv_nsec; int res = 0; Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t)); @@ -303,7 +328,7 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise) if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { if (raise) { - _PyTime_overflow(); + pytime_overflow(); res = -1; } t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; @@ -312,21 +337,21 @@ pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise) t = t * SEC_TO_NS; } - nsec = ts->tv_nsec; - /* The following test is written for positive only nsec */ - assert(nsec >= 0); - if (t > _PyTime_MAX - nsec) { + tv_nsec = ts->tv_nsec; + /* The following test is written for positive only tv_nsec */ + assert(tv_nsec >= 0); + if (t > _PyTime_MAX - tv_nsec) { if (raise) { - _PyTime_overflow(); + pytime_overflow(); res = -1; } t = _PyTime_MAX; } else { - t += nsec; + t += tv_nsec; } - *tp = t; + *tp = pytime_from_nanoseconds(t); return res; } @@ -337,6 +362,7 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) } #endif + #if !defined(MS_WINDOWS) static int pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) @@ -349,7 +375,7 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) if (_PyTime_check_mul_overflow(t, SEC_TO_NS)) { if (raise) { - _PyTime_overflow(); + pytime_overflow(); res = -1; } t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; @@ -363,7 +389,7 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) assert(usec >= 0); if (t > _PyTime_MAX - usec) { if (raise) { - _PyTime_overflow(); + pytime_overflow(); res = -1; } t = _PyTime_MAX; @@ -372,10 +398,11 @@ pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) t += usec; } - *tp = t; + *tp = pytime_from_nanoseconds(t); return res; } + int _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv) { @@ -383,8 +410,9 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv) } #endif + static int -_PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round, +pytime_from_double(_PyTime_t *tp, double value, _PyTime_round_t round, long unit_to_ns) { /* volatile avoids optimization changing how numbers are rounded */ @@ -393,18 +421,21 @@ _PyTime_FromDouble(_PyTime_t *t, double value, _PyTime_round_t round, /* convert to a number of nanoseconds */ d = value; d *= (double)unit_to_ns; - d = _PyTime_Round(d, round); + d = pytime_round(d, round); if (!_Py_InIntegralTypeRange(_PyTime_t, d)) { - _PyTime_overflow(); + pytime_overflow(); return -1; } - *t = (_PyTime_t)d; + _PyTime_t ns = (_PyTime_t)d; + + *tp = pytime_from_nanoseconds(ns); return 0; } + static int -_PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, +pytime_from_object(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round, long unit_to_ns) { if (PyFloat_Check(obj)) { @@ -414,71 +445,77 @@ _PyTime_FromObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round, PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)"); return -1; } - return _PyTime_FromDouble(t, d, round, unit_to_ns); + return pytime_from_double(tp, d, round, unit_to_ns); } else { - long long sec; Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t)); - - sec = PyLong_AsLongLong(obj); + long long sec = PyLong_AsLongLong(obj); if (sec == -1 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_OverflowError)) { - _PyTime_overflow(); + pytime_overflow(); } return -1; } if (_PyTime_check_mul_overflow(sec, unit_to_ns)) { - _PyTime_overflow(); + pytime_overflow(); return -1; } - *t = sec * unit_to_ns; + _PyTime_t ns = sec * unit_to_ns; + + *tp = pytime_from_nanoseconds(ns); return 0; } } -int -_PyTime_FromSecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) -{ - return _PyTime_FromObject(t, obj, round, SEC_TO_NS); -} int -_PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) +_PyTime_FromSecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round) { - return _PyTime_FromObject(t, obj, round, MS_TO_NS); + return pytime_from_object(tp, obj, round, SEC_TO_NS); } + +int +_PyTime_FromMillisecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round) +{ + return pytime_from_object(tp, obj, round, MS_TO_NS); +} + + double _PyTime_AsSecondsDouble(_PyTime_t t) { /* volatile avoids optimization changing how numbers are rounded */ volatile double d; - if (t % SEC_TO_NS == 0) { - _PyTime_t secs; + _PyTime_t ns = pytime_as_nanoseconds(t); + if (ns % SEC_TO_NS == 0) { /* Divide using integers to avoid rounding issues on the integer part. 1e-9 cannot be stored exactly in IEEE 64-bit. */ - secs = t / SEC_TO_NS; + _PyTime_t secs = ns / SEC_TO_NS; d = (double)secs; } else { - d = (double)t; + d = (double)ns; d /= 1e9; } return d; } + PyObject * _PyTime_AsNanosecondsObject(_PyTime_t t) { + _PyTime_t ns = pytime_as_nanoseconds(t); Py_BUILD_ASSERT(sizeof(long long) >= sizeof(_PyTime_t)); - return PyLong_FromLongLong((long long)t); + return PyLong_FromLongLong((long long)ns); } + static _PyTime_t -_PyTime_Divide(const _PyTime_t t, const _PyTime_t k, - const _PyTime_round_t round) +pytime_divide(const _PyTime_t t, const _PyTime_t k, + const _PyTime_round_t round) { assert(k > 1); if (round == _PyTime_ROUND_HALF_EVEN) { @@ -523,66 +560,77 @@ _PyTime_Divide(const _PyTime_t t, const _PyTime_t k, } } + _PyTime_t -_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) +_PyTime_AsNanoseconds(_PyTime_t t) { - return _PyTime_Divide(t, NS_TO_MS, round); + return pytime_as_nanoseconds(t); } + _PyTime_t _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) { - return _PyTime_Divide(t, NS_TO_US, round); + _PyTime_t ns = pytime_as_nanoseconds(t); + return pytime_divide(ns, NS_TO_US, round); } -static int -_PyTime_AsTimeval_impl(_PyTime_t t, _PyTime_t *p_secs, int *p_us, - _PyTime_round_t round) + +_PyTime_t +_PyTime_AsMilliseconds(_PyTime_t t, _PyTime_round_t round) { - _PyTime_t secs, ns; - int usec; + _PyTime_t ns = pytime_as_nanoseconds(t); + return pytime_divide(ns, NS_TO_MS, round); +} + + +static int +pytime_as_timeval(_PyTime_t t, _PyTime_t *p_secs, int *p_us, + _PyTime_round_t round) +{ + _PyTime_t ns, tv_sec; + ns = pytime_as_nanoseconds(t); + tv_sec = ns / SEC_TO_NS; + ns = ns % SEC_TO_NS; + + int tv_usec = (int)pytime_divide(ns, US_TO_NS, round); int res = 0; - - secs = t / SEC_TO_NS; - ns = t % SEC_TO_NS; - - usec = (int)_PyTime_Divide(ns, US_TO_NS, round); - if (usec < 0) { - usec += SEC_TO_US; - if (secs != _PyTime_MIN) { - secs -= 1; + if (tv_usec < 0) { + tv_usec += SEC_TO_US; + if (tv_sec != _PyTime_MIN) { + tv_sec -= 1; } else { res = -1; } } - else if (usec >= SEC_TO_US) { - usec -= SEC_TO_US; - if (secs != _PyTime_MAX) { - secs += 1; + else if (tv_usec >= SEC_TO_US) { + tv_usec -= SEC_TO_US; + if (tv_sec != _PyTime_MAX) { + tv_sec += 1; } else { res = -1; } } - assert(0 <= usec && usec < SEC_TO_US); + assert(0 <= tv_usec && tv_usec < SEC_TO_US); - *p_secs = secs; - *p_us = usec; + *p_secs = tv_sec; + *p_us = tv_usec; return res; } + static int -_PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, - _PyTime_round_t round, int raise) +pytime_as_timeval_struct(_PyTime_t t, struct timeval *tv, + _PyTime_round_t round, int raise) { _PyTime_t secs, secs2; int us; int res; - res = _PyTime_AsTimeval_impl(t, &secs, &us, round); - + res = pytime_as_timeval(t, &secs, &us, round); #ifdef MS_WINDOWS tv->tv_sec = (long)secs; #else @@ -593,38 +641,39 @@ _PyTime_AsTimevalStruct_impl(_PyTime_t t, struct timeval *tv, secs2 = (_PyTime_t)tv->tv_sec; if (res < 0 || secs2 != secs) { if (raise) { - error_time_t_overflow(); + pytime_time_t_overflow(); } return -1; } return 0; } + int _PyTime_AsTimeval(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) { - return _PyTime_AsTimevalStruct_impl(t, tv, round, 1); + return pytime_as_timeval_struct(t, tv, round, 1); } + int _PyTime_AsTimeval_noraise(_PyTime_t t, struct timeval *tv, _PyTime_round_t round) { - return _PyTime_AsTimevalStruct_impl(t, tv, round, 0); + return pytime_as_timeval_struct(t, tv, round, 0); } + int _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, _PyTime_round_t round) { _PyTime_t secs; - int res; + int res = pytime_as_timeval(t, &secs, us, round); - res = _PyTime_AsTimeval_impl(t, &secs, us, round); - - *p_secs = secs; + *p_secs = (time_t)secs; if (res < 0 || (_PyTime_t)*p_secs != secs) { - error_time_t_overflow(); + pytime_time_t_overflow(); return -1; } return 0; @@ -635,26 +684,28 @@ _PyTime_AsTimevalTime_t(_PyTime_t t, time_t *p_secs, int *us, int _PyTime_AsTimespec(_PyTime_t t, struct timespec *ts) { - _PyTime_t secs, nsec; + _PyTime_t tv_sec, tv_nsec; - secs = t / SEC_TO_NS; - nsec = t % SEC_TO_NS; - if (nsec < 0) { - nsec += SEC_TO_NS; - secs -= 1; + _PyTime_t ns = pytime_as_nanoseconds(t); + tv_sec = ns / SEC_TO_NS; + tv_nsec = ns % SEC_TO_NS; + if (tv_nsec < 0) { + tv_nsec += SEC_TO_NS; + tv_sec -= 1; } - ts->tv_sec = (time_t)secs; - assert(0 <= nsec && nsec < SEC_TO_NS); - ts->tv_nsec = nsec; + ts->tv_sec = (time_t)tv_sec; + assert(0 <= tv_nsec && tv_nsec < SEC_TO_NS); + ts->tv_nsec = tv_nsec; - if ((_PyTime_t)ts->tv_sec != secs) { - error_time_t_overflow(); + if ((_PyTime_t)ts->tv_sec != tv_sec) { + pytime_time_t_overflow(); return -1; } return 0; } #endif + static int py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) { @@ -670,7 +721,8 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) /* 11,644,473,600,000,000,000: number of nanoseconds between the 1st january 1601 and the 1st january 1970 (369 years + 89 leap days). */ - *tp = large.QuadPart * 100 - 11644473600000000000; + _PyTime_t ns = large.QuadPart * 100 - 11644473600000000000; + *tp = pytime_from_nanoseconds(ns); if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled, ok; @@ -730,7 +782,8 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) } #ifdef HAVE_CLOCK_GETTIME_RUNTIME - } else { + } + else { #endif #endif @@ -765,6 +818,7 @@ py_get_system_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) return 0; } + _PyTime_t _PyTime_GetSystemClock(void) { @@ -777,12 +831,14 @@ _PyTime_GetSystemClock(void) return t; } + int _PyTime_GetSystemClockWithInfo(_PyTime_t *t, _Py_clock_info_t *info) { return py_get_system_clock(t, info, 1); } + #if __APPLE__ static int py_mach_timebase_info(_PyTime_t *pnumer, _PyTime_t *pdenom, int raise) @@ -848,7 +904,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) if (_PyTime_check_mul_overflow(t, MS_TO_NS)) { if (raise) { - _PyTime_overflow(); + pytime_overflow(); return -1; } // Truncate to _PyTime_MAX silently. @@ -889,8 +945,13 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) info->adjustable = 0; } - uint64_t ticks = mach_absolute_time(); - *tp = _PyTime_MulDiv((_PyTime_t)ticks, timebase_numer, timebase_denom); + uint64_t uticks = mach_absolute_time(); + // unsigned => signed + assert(uticks <= (uint64_t)_PyTime_MAX); + _PyTime_t ticks = (_PyTime_t)uticks; + + _PyTime_t ns = _PyTime_MulDiv(ticks, timebase_numer, timebase_denom); + *tp = pytime_from_nanoseconds(ns); #elif defined(__hpux) hrtime_t time; @@ -903,7 +964,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) return -1; } - *tp = time; + *tp = pytime_from_nanoseconds(time); if (info) { info->implementation = "gethrtime()"; @@ -950,6 +1011,7 @@ py_get_monotonic_clock(_PyTime_t *tp, _Py_clock_info_t *info, int raise) return 0; } + _PyTime_t _PyTime_GetMonotonicClock(void) { @@ -962,6 +1024,7 @@ _PyTime_GetMonotonicClock(void) return t; } + int _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) { @@ -971,7 +1034,7 @@ _PyTime_GetMonotonicClockWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) #ifdef MS_WINDOWS static int -win_perf_counter_frequency(LONGLONG *pfrequency, int raise) +py_win_perf_counter_frequency(LONGLONG *pfrequency, int raise) { LONGLONG frequency; @@ -1025,7 +1088,7 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise) { static LONGLONG frequency = 0; if (frequency == 0) { - if (win_perf_counter_frequency(&frequency, raise) < 0) { + if (py_win_perf_counter_frequency(&frequency, raise) < 0) { return -1; } } @@ -1047,7 +1110,8 @@ py_get_win_perf_counter(_PyTime_t *tp, _Py_clock_info_t *info, int raise) Py_BUILD_ASSERT(sizeof(ticksll) <= sizeof(ticks)); ticks = (_PyTime_t)ticksll; - *tp = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency); + _PyTime_t ns = _PyTime_MulDiv(ticks, SEC_TO_NS, (_PyTime_t)frequency); + *tp = pytime_from_nanoseconds(ns); return 0; } #endif @@ -1075,8 +1139,8 @@ _PyTime_GetPerfCounter(void) res = py_get_monotonic_clock(&t, NULL, 0); #endif if (res < 0) { - // If win_perf_counter_frequency() or py_get_monotonic_clock() fails: - // silently ignore the failure and return 0. + // If py_win_perf_counter_frequency() or py_get_monotonic_clock() + // fails: silently ignore the failure and return 0. t = 0; } return t; @@ -1121,6 +1185,7 @@ _PyTime_localtime(time_t t, struct tm *tm) #endif /* MS_WINDOWS */ } + int _PyTime_gmtime(time_t t, struct tm *tm) {