From 9677760e69d97e7d93d06a47eb62dadde81c8bee Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 15 Sep 2021 12:40:05 +0200 Subject: [PATCH] bpo-21302: Add _PyTime_AsNanoseconds() Refactor pytime.c: * Add pytime_from_nanoseconds() and pytime_as_nanoseconds(), and use explicitly these functions * Add two empty lines between functions * PEP 7: add braces { ... } * C99: declare variables where they are set * Rename private functions to lowercase * Rename error_time_t_overflow() to pytime_time_t_overflow() * Rename win_perf_counter_frequency() to py_win_perf_counter_frequency() * py_get_monotonic_clock(): add an assertion to detect overflow when mach_absolute_time() unsigned uint64_t is casted to _PyTime_t (signed int64_t). _testcapi: use _PyTime_FromNanoseconds(). --- Include/cpython/pytime.h | 3 + Modules/_testcapimodule.c | 64 ++++---- Modules/timemodule.c | 16 +- Python/pytime.c | 311 +++++++++++++++++++++++--------------- 4 files changed, 228 insertions(+), 166 deletions(-) diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h index 56607d199ed542..b0453884398cbf 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 b1e64f19f2d145..51323f03e23689 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; - _PyTime_t ts; - - if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) + if (!PyArg_ParseTuple(args, "Oi", &obj, &round)) { return NULL; - if (check_time_rounding(round) < 0) + } + if (check_time_rounding(round) < 0) { return NULL; - if (_PyTime_FromSecondsObject(&ts, obj, round) == -1) + } + _PyTime_t ts; + 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 cf58a18caf1f20..52c61154f3a05b 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 1ef99aee748466..8035a5f8a28b48 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) +_PyTime_FromSecondsObject(_PyTime_t *tp, PyObject *obj, _PyTime_round_t round) { - return _PyTime_FromObject(t, obj, round, SEC_TO_NS); + return pytime_from_object(tp, obj, round, SEC_TO_NS); } + int -_PyTime_FromMillisecondsObject(_PyTime_t *t, PyObject *obj, _PyTime_round_t round) +_PyTime_FromMillisecondsObject(_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, 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; - int res = 0; + _PyTime_t ns = pytime_as_nanoseconds(t); + return pytime_divide(ns, NS_TO_MS, round); +} - 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; +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; + 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) { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy