diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-11-02 14:28:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-02 14:28:27 (GMT) |
commit | c29b585fd4b5a91d17fc5dd41d86edff28a30da3 (patch) | |
tree | aadcf238ccc1867d7adefc079081781424e3e62c /Python/pytime.c | |
parent | e314853d57450b2b9523157eebd405289a795a0e (diff) | |
download | cpython-c29b585fd4b5a91d17fc5dd41d86edff28a30da3.zip cpython-c29b585fd4b5a91d17fc5dd41d86edff28a30da3.tar.gz cpython-c29b585fd4b5a91d17fc5dd41d86edff28a30da3.tar.bz2 |
bpo-31784: Implement PEP 564: add time.time_ns() (#3989)
Add new time functions:
* time.clock_gettime_ns()
* time.clock_settime_ns()
* time.monotonic_ns()
* time.perf_counter_ns()
* time.process_time_ns()
* time.time_ns()
Add new _PyTime functions:
* _PyTime_FromTimespec()
* _PyTime_FromNanosecondsObject()
* _PyTime_FromTimeval()
Other changes:
* Add also os.times() tests to test_os.
* pytime_fromtimeval() and pytime_fromtimeval() now return
_PyTime_MAX or _PyTime_MIN on overflow, rather than undefined
behaviour
* _PyTime_FromNanoseconds() parameter type changes from long long to
_PyTime_t
Diffstat (limited to 'Python/pytime.c')
-rw-r--r-- | Python/pytime.c | 105 |
1 files changed, 86 insertions, 19 deletions
diff --git a/Python/pytime.c b/Python/pytime.c index f19bb36..5a98d1d 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -43,8 +43,7 @@ _PyTime_overflow(void) } -#if defined(MS_WINDOWS) || defined(__APPLE__) -Py_LOCAL_INLINE(_PyTime_t) +_PyTime_t _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) { _PyTime_t intpart, remaining; @@ -60,7 +59,6 @@ _PyTime_MulDiv(_PyTime_t ticks, _PyTime_t mul, _PyTime_t div) remaining /= div; return intpart * mul + remaining; } -#endif /* defined(MS_WINDOWS) || defined(__APPLE__) */ time_t @@ -254,19 +252,44 @@ _PyTime_FromSeconds(int seconds) } _PyTime_t -_PyTime_FromNanoseconds(long long ns) +_PyTime_FromNanoseconds(_PyTime_t ns) +{ + /* _PyTime_t already uses nanosecond resolution, no conversion needed */ + return ns; +} + +int +_PyTime_FromNanosecondsObject(_PyTime_t *tp, PyObject *obj) { + long long nsec; _PyTime_t t; - Py_BUILD_ASSERT(sizeof(long long) <= sizeof(_PyTime_t)); - t = Py_SAFE_DOWNCAST(ns, long long, _PyTime_t); - return t; + + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "expect int, got %s", + Py_TYPE(obj)->tp_name); + return -1; + } + + Py_BUILD_ASSERT(sizeof(long long) == sizeof(_PyTime_t)); + nsec = PyLong_AsLongLong(obj); + if (nsec == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + _PyTime_overflow(); + } + return -1; + } + + /* _PyTime_t already uses nanosecond resolution, no conversion needed */ + t = (_PyTime_t)nsec; + *tp = t; + return 0; } #ifdef HAVE_CLOCK_GETTIME static int -_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise) +pytime_fromtimespec(_PyTime_t *tp, struct timespec *ts, int raise) { - _PyTime_t t; + _PyTime_t t, nsec; int res = 0; Py_BUILD_ASSERT(sizeof(ts->tv_sec) <= sizeof(_PyTime_t)); @@ -277,19 +300,42 @@ _PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts, int raise) _PyTime_overflow(); } res = -1; + t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; + } + else { + t = t * SEC_TO_NS; } - t = t * SEC_TO_NS; - t += ts->tv_nsec; + nsec = ts->tv_nsec; + /* The following test is written for positive only nsec */ + assert(nsec >= 0); + if (t > _PyTime_MAX - nsec) { + if (raise) { + _PyTime_overflow(); + } + res = -1; + t = _PyTime_MAX; + } + else { + t += nsec; + } *tp = t; return res; } -#elif !defined(MS_WINDOWS) + +int +_PyTime_FromTimespec(_PyTime_t *tp, struct timespec *ts) +{ + return pytime_fromtimespec(tp, ts, 1); +} +#endif + +#if !defined(MS_WINDOWS) static int -_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise) +pytime_fromtimeval(_PyTime_t *tp, struct timeval *tv, int raise) { - _PyTime_t t; + _PyTime_t t, usec; int res = 0; Py_BUILD_ASSERT(sizeof(tv->tv_sec) <= sizeof(_PyTime_t)); @@ -300,14 +346,35 @@ _PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv, int raise) _PyTime_overflow(); } res = -1; + t = (t > 0) ? _PyTime_MAX : _PyTime_MIN; + } + else { + t = t * SEC_TO_NS; } - t = t * SEC_TO_NS; - t += (_PyTime_t)tv->tv_usec * US_TO_NS; + usec = (_PyTime_t)tv->tv_usec * US_TO_NS; + /* The following test is written for positive only usec */ + assert(usec >= 0); + if (t > _PyTime_MAX - usec) { + if (raise) { + _PyTime_overflow(); + } + res = -1; + t = _PyTime_MAX; + } + else { + t += usec; + } *tp = t; return res; } + +int +_PyTime_FromTimeval(_PyTime_t *tp, struct timeval *tv) +{ + return pytime_fromtimeval(tp, tv, 1); +} #endif static int @@ -632,7 +699,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) } return -1; } - if (_PyTime_FromTimespec(tp, &ts, raise) < 0) { + if (pytime_fromtimespec(tp, &ts, raise) < 0) { return -1; } @@ -662,7 +729,7 @@ pygettimeofday(_PyTime_t *tp, _Py_clock_info_t *info, int raise) } return -1; } - if (_PyTime_FromTimeval(tp, &tv, raise) < 0) { + if (pytime_fromtimeval(tp, &tv, raise) < 0) { return -1; } @@ -841,7 +908,7 @@ pymonotonic(_PyTime_t *tp, _Py_clock_info_t *info, int raise) } info->resolution = res.tv_sec + res.tv_nsec * 1e-9; } - if (_PyTime_FromTimespec(tp, &ts, raise) < 0) { + if (pytime_fromtimespec(tp, &ts, raise) < 0) { return -1; } #endif |