From 23a8cad783fc1e7e418a79d1e8a8822d8f4a6225 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 7 Feb 2012 23:41:01 +0100 Subject: Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime() to have a resolution of 100 ns instead of 1 ms (the clock accuracy is between 0.5 ms and 15 ms). --- Python/pytime.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index 6fb7695911..bec1c713e6 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -1,7 +1,9 @@ #include "Python.h" +#ifdef MS_WINDOWS +#include +#endif -#ifdef __APPLE__ -#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) +#if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) /* * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter * might fail on some platforms. This fallback is unwanted on MacOSX because @@ -10,18 +12,30 @@ */ # undef HAVE_FTIME #endif -#endif -#ifdef HAVE_FTIME +#if defined(HAVE_FTIME) && !defined(MS_WINDOWS) #include -#if !defined(MS_WINDOWS) && !defined(PYOS_OS2) extern int ftime(struct timeb *); -#endif /* MS_WINDOWS */ -#endif /* HAVE_FTIME */ +#endif void _PyTime_gettimeofday(_PyTime_timeval *tp) { +#ifdef MS_WINDOWS + FILETIME system_time; + ULARGE_INTEGER large; + ULONGLONG microseconds; + + GetSystemTimeAsFileTime(&system_time); + large.u.LowPart = system_time.dwLowDateTime; + large.u.HighPart = system_time.dwHighDateTime; + /* 11,644,473,600,000,000: number of microseconds between + the 1st january 1601 and the 1st january 1970 (369 years + 89 leap + days). */ + microseconds = large.QuadPart / 10 - 11644473600000000; + tp->tv_sec = microseconds / 1000000; + tp->tv_usec = microseconds % 1000000; +#else /* There are three ways to get the time: (1) gettimeofday() -- resolution in microseconds (2) ftime() -- resolution in milliseconds @@ -30,6 +44,7 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may fail, so we fall back on ftime() or time(). Note: clock resolution does not imply clock accuracy! */ + #ifdef HAVE_GETTIMEOFDAY #ifdef GETTIMEOFDAY_NO_TZ if (gettimeofday(tp) == 0) @@ -39,6 +54,7 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) return; #endif /* !GETTIMEOFDAY_NO_TZ */ #endif /* !HAVE_GETTIMEOFDAY */ + #if defined(HAVE_FTIME) { struct timeb t; @@ -50,7 +66,8 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) tp->tv_sec = time(NULL); tp->tv_usec = 0; #endif /* !HAVE_FTIME */ - return; + +#endif /* MS_WINDOWS */ } void -- cgit v1.2.1 From 9444533c014ebfd2aed80f40ce8d15ce5c675a40 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 2 Mar 2012 22:54:03 +0100 Subject: Issue #13964: signal.sigtimedwait() timeout is now a float instead of a tuple Add a private API to convert an int or float to a C timespec structure. --- Python/pytime.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index bec1c713e6..d23ce75b43 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -70,6 +70,51 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) #endif /* MS_WINDOWS */ } +int +_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +{ + if (PyFloat_Check(obj)) { + double d, intpart, floatpart, err; + + d = PyFloat_AsDouble(obj); + floatpart = modf(d, &intpart); + if (floatpart < 0) { + floatpart = 1.0 + floatpart; + intpart -= 1.0; + } + + *sec = (time_t)intpart; + err = intpart - (double)*sec; + if (err <= -1.0 || err >= 1.0) + goto overflow; + + floatpart *= 1e9; + *nsec = (long)floatpart; + return 0; + } + else { +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + *sec = PyLong_AsLongLong(obj); +#else + assert(sizeof(time_t) <= sizeof(long)); + *sec = PyLong_AsLong(obj); +#endif + if (*sec == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + goto overflow; + else + return -1; + } + *nsec = 0; + return 0; + } + +overflow: + PyErr_SetString(PyExc_OverflowError, + "timestamp out of range for platform time_t"); + return -1; +} + void _PyTime_Init() { -- cgit v1.2.1 From adce5ff128974a4206a25388f449633c579d4e8a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 13:35:55 +0100 Subject: Close #14180: Factorize code to convert a number of seconds to time_t, timeval or timespec time.ctime(), gmtime(), time.localtime(), datetime.date.fromtimestamp(), datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now raises an OverflowError, instead of a ValueError, if the timestamp does not fit in time_t. datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now round microseconds towards zero instead of rounding to nearest with ties going away from zero. --- Python/pytime.c | 99 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 77 insertions(+), 22 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index d23ce75b43..79a1a33616 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -70,9 +70,37 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) #endif /* MS_WINDOWS */ } -int -_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +static void +error_time_t_overflow(void) +{ + PyErr_SetString(PyExc_OverflowError, + "timestamp out of range for platform time_t"); +} + +static time_t +_PyLong_AsTime_t(PyObject *obj) +{ +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + PY_LONG_LONG val; + val = PyLong_AsLongLong(obj); +#else + long val; + assert(sizeof(time_t) <= sizeof(long)); + val = PyLong_AsLong(obj); +#endif + if (val == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) + error_time_t_overflow(); + return -1; + } + return (time_t)val; +} + +static int +_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, + double denominator) { + assert(denominator <= LONG_MAX); if (PyFloat_Check(obj)) { double d, intpart, floatpart, err; @@ -85,34 +113,61 @@ _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) *sec = (time_t)intpart; err = intpart - (double)*sec; - if (err <= -1.0 || err >= 1.0) - goto overflow; + if (err <= -1.0 || err >= 1.0) { + error_time_t_overflow(); + return -1; + } - floatpart *= 1e9; - *nsec = (long)floatpart; + floatpart *= denominator; + *numerator = (long)floatpart; return 0; } else { -#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG - *sec = PyLong_AsLongLong(obj); -#else - assert(sizeof(time_t) <= sizeof(long)); - *sec = PyLong_AsLong(obj); -#endif - if (*sec == -1 && PyErr_Occurred()) { - if (PyErr_ExceptionMatches(PyExc_OverflowError)) - goto overflow; - else - return -1; + *sec = _PyLong_AsTime_t(obj); + if (*sec == (time_t)-1 && PyErr_Occurred()) + return -1; + *numerator = 0; + return 0; + } +} + +int +_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec) +{ + if (PyFloat_Check(obj)) { + double d, intpart, err; + + /*whent = _PyTime_DoubleToTimet(d);*/ + + d = PyFloat_AsDouble(obj); + (void)modf(d, &intpart); + + *sec = (time_t)intpart; + err = intpart - (double)*sec; + if (err <= -1.0 || err >= 1.0) { + error_time_t_overflow(); + return -1; } - *nsec = 0; return 0; } + else { + *sec = _PyLong_AsTime_t(obj); + if (*sec == (time_t)-1 && PyErr_Occurred()) + return -1; + return 0; + } +} -overflow: - PyErr_SetString(PyExc_OverflowError, - "timestamp out of range for platform time_t"); - return -1; +int +_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec) +{ + return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9); +} + +int +_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec) +{ + return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6); } void -- cgit v1.2.1 From 08a3385bd19cd7a0ac32758f3f24fbdd49ad4fda Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 13:50:34 +0100 Subject: Issue #14180: Remove commented code --- Python/pytime.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index 79a1a33616..75d80e2576 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -137,8 +137,6 @@ _PyTime_ObjectToTime_t(PyObject *obj, time_t *sec) if (PyFloat_Check(obj)) { double d, intpart, err; - /*whent = _PyTime_DoubleToTimet(d);*/ - d = PyFloat_AsDouble(obj); (void)modf(d, &intpart); -- cgit v1.2.1 From 75ff7e8c4aa9633a8c87788c24ab8335fa1dd698 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 13 Mar 2012 19:12:23 +0100 Subject: Issue #14180: Fix an invalid rounding when compiler optimization are enabled Use volatile keyword to disable localy unsafe float optimizations. --- Python/pytime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index 75d80e2576..e7dadc7605 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -102,7 +102,9 @@ _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, { assert(denominator <= LONG_MAX); if (PyFloat_Check(obj)) { - double d, intpart, floatpart, err; + double d, intpart, err; + /* volatile avoids unsafe optimization on float enabled by gcc -O3 */ + volatile double floatpart; d = PyFloat_AsDouble(obj); floatpart = modf(d, &intpart); -- cgit v1.2.1 From 3921635bee5d2560a5017891c6e5ee3d6b06c32c Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Thu, 19 Apr 2012 15:07:49 -0700 Subject: Issue #14127: Add st_{cma}time_ns fields to os.stat() result object. --- Python/pytime.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index e7dadc7605..db3f683064 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -96,6 +96,17 @@ _PyLong_AsTime_t(PyObject *obj) return (time_t)val; } +PyObject * +_PyLong_FromTime_t(time_t t) +{ +#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG + return PyLong_FromLongLong((PY_LONG_LONG)t); +#else + assert(sizeof(time_t) <= sizeof(long)); + return PyLong_FromLong((long)t); +#endif +} + static int _PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator, double denominator) -- cgit v1.2.1 From d5f225bf1a19028958c3e8a4ce559ffe435721ed Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 29 Apr 2012 02:41:27 +0200 Subject: Issue #14428, #14397: Implement the PEP 418 * Rename time.steady() to time.monotonic() * On Windows, time.monotonic() uses GetTickCount/GetTickCount64() instead of QueryPerformanceCounter() * time.monotonic() uses CLOCK_HIGHRES if available * Add time.get_clock_info(), time.perf_counter() and time.process_time() functions --- Python/pytime.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index db3f683064..ddd3088405 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -18,8 +18,8 @@ extern int ftime(struct timeb *); #endif -void -_PyTime_gettimeofday(_PyTime_timeval *tp) +static void +pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) { #ifdef MS_WINDOWS FILETIME system_time; @@ -35,6 +35,20 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) microseconds = large.QuadPart / 10 - 11644473600000000; tp->tv_sec = microseconds / 1000000; tp->tv_usec = microseconds % 1000000; + if (info) { + DWORD timeAdjustment, timeIncrement; + BOOL isTimeAdjustmentDisabled; + + info->implementation = "GetSystemTimeAsFileTime()"; + info->is_monotonic = 0; + (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, + &isTimeAdjustmentDisabled); + info->resolution = timeIncrement * 1e-7; + if (isTimeAdjustmentDisabled) + info->is_adjusted = 0; + else + info->is_adjusted = 1; + } #else /* There are three ways to get the time: (1) gettimeofday() -- resolution in microseconds @@ -46,14 +60,22 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) Note: clock resolution does not imply clock accuracy! */ #ifdef HAVE_GETTIMEOFDAY + int err; #ifdef GETTIMEOFDAY_NO_TZ - if (gettimeofday(tp) == 0) - return; -#else /* !GETTIMEOFDAY_NO_TZ */ - if (gettimeofday(tp, (struct timezone *)NULL) == 0) + err = gettimeofday(tp); +#else + err = gettimeofday(tp, (struct timezone *)NULL); +#endif + if (err == 0) { + if (info) { + info->implementation = "gettimeofday()"; + info->resolution = 1e-6; + info->is_monotonic = 0; + info->is_adjusted = 1; + } return; -#endif /* !GETTIMEOFDAY_NO_TZ */ -#endif /* !HAVE_GETTIMEOFDAY */ + } +#endif /* HAVE_GETTIMEOFDAY */ #if defined(HAVE_FTIME) { @@ -61,15 +83,39 @@ _PyTime_gettimeofday(_PyTime_timeval *tp) ftime(&t); tp->tv_sec = t.time; tp->tv_usec = t.millitm * 1000; + if (info) { + info->implementation = "ftime()"; + info->resolution = 1e-3; + info->is_monotonic = 0; + info->is_adjusted = 1; + } } #else /* !HAVE_FTIME */ tp->tv_sec = time(NULL); tp->tv_usec = 0; + if (info) { + info->implementation = "time()"; + info->resolution = 1.0; + info->is_monotonic = 0; + info->is_adjusted = 1; + } #endif /* !HAVE_FTIME */ #endif /* MS_WINDOWS */ } +void +_PyTime_gettimeofday(_PyTime_timeval *tp) +{ + pygettimeofday(tp, NULL); +} + +void +_PyTime_gettimeofday_info(_PyTime_timeval *tp, _Py_clock_info_t *info) +{ + pygettimeofday(tp, info); +} + static void error_time_t_overflow(void) { -- cgit v1.2.1 From 263dd2cba4d8cadc8ffbb8fd582aa1b5190a431b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 1 May 2012 09:38:34 -0400 Subject: strip is_ prefixes on clock_info fields --- Python/pytime.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index ddd3088405..0ffe799b32 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -40,14 +40,14 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) BOOL isTimeAdjustmentDisabled; info->implementation = "GetSystemTimeAsFileTime()"; - info->is_monotonic = 0; + info->monotonic = 0; (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); info->resolution = timeIncrement * 1e-7; if (isTimeAdjustmentDisabled) - info->is_adjusted = 0; + info->adjusted = 0; else - info->is_adjusted = 1; + info->adjusted = 1; } #else /* There are three ways to get the time: @@ -70,8 +70,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) if (info) { info->implementation = "gettimeofday()"; info->resolution = 1e-6; - info->is_monotonic = 0; - info->is_adjusted = 1; + info->monotonic = 0; + info->adjusted = 1; } return; } @@ -86,8 +86,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) if (info) { info->implementation = "ftime()"; info->resolution = 1e-3; - info->is_monotonic = 0; - info->is_adjusted = 1; + info->monotonic = 0; + info->adjusted = 1; } } #else /* !HAVE_FTIME */ @@ -96,8 +96,8 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) if (info) { info->implementation = "time()"; info->resolution = 1.0; - info->is_monotonic = 0; - info->is_adjusted = 1; + info->monotonic = 0; + info->adjusted = 1; } #endif /* !HAVE_FTIME */ -- cgit v1.2.1 From ddc066b19031d00f7e7e57803c2fbafe4c2c6d4b Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Thu, 3 May 2012 00:30:07 -0700 Subject: Issue #14127: Add ns= parameter to utime, futimes, and lutimes. Removed futimens as it is now redundant. Changed shutil.copystat to use st_atime_ns and st_mtime_ns from os.stat and ns= parameter to utime--it once again preserves exact metadata on Linux! --- Python/pytime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index 0ffe799b32..eb5685b987 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -123,7 +123,7 @@ error_time_t_overflow(void) "timestamp out of range for platform time_t"); } -static time_t +time_t _PyLong_AsTime_t(PyObject *obj) { #if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG -- cgit v1.2.1 From fe9aae83beed32365feb8e9661c20fb6f5bd1c6d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 12 Jun 2012 22:46:37 +0200 Subject: PEP 418: Rename adjusted attribute to adjustable in time.get_clock_info() result Fix also its value on Windows and Linux according to its documentation: "adjustable" indicates if the clock *can be* adjusted, not if it is or was adjusted. In most cases, it is not possible to indicate if a clock is or was adjusted. --- Python/pytime.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'Python/pytime.c') diff --git a/Python/pytime.c b/Python/pytime.c index eb5685b987..beeab87e2c 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -44,10 +44,7 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) (void) GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); info->resolution = timeIncrement * 1e-7; - if (isTimeAdjustmentDisabled) - info->adjusted = 0; - else - info->adjusted = 1; + info->adjustable = 1; } #else /* There are three ways to get the time: @@ -71,7 +68,7 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) info->implementation = "gettimeofday()"; info->resolution = 1e-6; info->monotonic = 0; - info->adjusted = 1; + info->adjustable = 1; } return; } @@ -87,7 +84,7 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) info->implementation = "ftime()"; info->resolution = 1e-3; info->monotonic = 0; - info->adjusted = 1; + info->adjustable = 1; } } #else /* !HAVE_FTIME */ @@ -97,7 +94,7 @@ pygettimeofday(_PyTime_timeval *tp, _Py_clock_info_t *info) info->implementation = "time()"; info->resolution = 1.0; info->monotonic = 0; - info->adjusted = 1; + info->adjustable = 1; } #endif /* !HAVE_FTIME */ -- cgit v1.2.1