bpo-21302: Add _PyTime_AsNanoseconds() (GH-28350)

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().
This commit is contained in:
Victor Stinner 2021-09-15 14:26:43 +02:00 committed by GitHub
parent 40d2ac92f9
commit b49263b698
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 233 additions and 171 deletions

View File

@ -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);

View File

@ -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*

View File

@ -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;
}
}

View File

@ -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)
{