summaryrefslogtreecommitdiffstats
path: root/Python/pytime.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2017-11-02 14:28:27 (GMT)
committerGitHub <noreply@github.com>2017-11-02 14:28:27 (GMT)
commitc29b585fd4b5a91d17fc5dd41d86edff28a30da3 (patch)
treeaadcf238ccc1867d7adefc079081781424e3e62c /Python/pytime.c
parente314853d57450b2b9523157eebd405289a795a0e (diff)
downloadcpython-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.c105
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