diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2014-09-02 21:18:25 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2014-09-02 21:18:25 (GMT) |
commit | ae58649721ec898ea4a101b0861e16fff3511cfa (patch) | |
tree | bb08b1a9b5f354212d7ca365d76659b09aed879a /Modules | |
parent | 9bb758cee7f1694807ebe600b6230fb8e565d3ea (diff) | |
download | cpython-ae58649721ec898ea4a101b0861e16fff3511cfa.zip cpython-ae58649721ec898ea4a101b0861e16fff3511cfa.tar.gz cpython-ae58649721ec898ea4a101b0861e16fff3511cfa.tar.bz2 |
Issue #22043: time.monotonic() is now always available
threading.Lock.acquire(), threading.RLock.acquire() and socket operations now
use a monotonic clock, instead of the system clock, when a timeout is used.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_threadmodule.c | 4 | ||||
-rw-r--r-- | Modules/gcmodule.c | 6 | ||||
-rw-r--r-- | Modules/socketmodule.c | 4 | ||||
-rw-r--r-- | Modules/timemodule.c | 141 |
4 files changed, 13 insertions, 142 deletions
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index b68c177..8f59e03 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -57,7 +57,7 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) if (microseconds > 0) { - _PyTime_gettimeofday(&endtime); + _PyTime_monotonic(&endtime); endtime.tv_sec += microseconds / (1000 * 1000); endtime.tv_usec += microseconds % (1000 * 1000); } @@ -83,7 +83,7 @@ acquire_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds) /* If we're using a timeout, recompute the timeout after processing * signals, since those can take time. */ if (microseconds > 0) { - _PyTime_gettimeofday(&curtime); + _PyTime_monotonic(&curtime); microseconds = ((endtime.tv_sec - curtime.tv_sec) * 1000000 + (endtime.tv_usec - curtime.tv_usec)); diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 5e8e17b..142687b 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -25,7 +25,7 @@ #include "Python.h" #include "frameobject.h" /* for PyFrame_ClearFreeList */ -#include "pytime.h" /* for _PyTime_gettimeofday, _PyTime_INTERVAL */ +#include "pytime.h" /* for _PyTime_monotonic, _PyTime_INTERVAL */ /* Get an object's GC head */ #define AS_GC(o) ((PyGC_Head *)(o)-1) @@ -919,7 +919,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, for (i = 0; i < NUM_GENERATIONS; i++) PySys_FormatStderr(" %zd", gc_list_size(GEN_HEAD(i))); - _PyTime_gettimeofday(&t1); + _PyTime_monotonic(&t1); PySys_WriteStderr("\n"); } @@ -1025,7 +1025,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, } if (debug & DEBUG_STATS) { _PyTime_timeval t2; - _PyTime_gettimeofday(&t2); + _PyTime_monotonic(&t2); if (m == 0 && n == 0) PySys_WriteStderr("gc: done"); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index abadd8a..db69d6e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -680,7 +680,7 @@ internal_select(PySocketSockObject *s, int writing) double interval = s->sock_timeout; \ int has_timeout = s->sock_timeout > 0.0; \ if (has_timeout) { \ - _PyTime_gettimeofday(&now); \ + _PyTime_monotonic(&now); \ deadline = now; \ _PyTime_ADD_SECONDS(deadline, s->sock_timeout); \ } \ @@ -691,7 +691,7 @@ internal_select(PySocketSockObject *s, int writing) if (!has_timeout || \ (!CHECK_ERRNO(EWOULDBLOCK) && !CHECK_ERRNO(EAGAIN))) \ break; \ - _PyTime_gettimeofday(&now); \ + _PyTime_monotonic(&now); \ interval = _PyTime_INTERVAL(now, deadline); \ } \ } \ diff --git a/Modules/timemodule.c b/Modules/timemodule.c index c90d8f9..16f4f6d 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -37,10 +37,6 @@ #endif /* MS_WINDOWS */ #endif /* !__WATCOMC__ || __QNX__ */ -#if defined(__APPLE__) -#include <mach/mach_time.h> -#endif - /* Forward declarations */ static int floatsleep(double); static PyObject* floattime(_Py_clock_info_t *info); @@ -899,122 +895,15 @@ the local timezone used by methods such as localtime, but this behaviour\n\ should not be relied on."); #endif /* HAVE_WORKING_TZSET */ -#if defined(MS_WINDOWS) || defined(__APPLE__) \ - || (defined(HAVE_CLOCK_GETTIME) \ - && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC))) -#define PYMONOTONIC -#endif - -#ifdef PYMONOTONIC -static PyObject* +static PyObject * pymonotonic(_Py_clock_info_t *info) { -#if defined(MS_WINDOWS) - static ULONGLONG (*GetTickCount64) (void) = NULL; - static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); - static int has_getickcount64 = -1; - double result; - - if (has_getickcount64 == -1) { - /* GetTickCount64() was added to Windows Vista */ - if (winver.dwMajorVersion >= 6) { - HINSTANCE hKernel32; - hKernel32 = GetModuleHandleW(L"KERNEL32"); - *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, - "GetTickCount64"); - has_getickcount64 = (Py_GetTickCount64 != NULL); - } - else - has_getickcount64 = 0; - } - - if (has_getickcount64) { - ULONGLONG ticks; - ticks = Py_GetTickCount64(); - result = (double)ticks * 1e-3; - } - else { - static DWORD last_ticks = 0; - static DWORD n_overflow = 0; - DWORD ticks; - - ticks = GetTickCount(); - if (ticks < last_ticks) - n_overflow++; - last_ticks = ticks; - - result = ldexp(n_overflow, 32); - result += ticks; - result *= 1e-3; - } - - if (info) { - DWORD timeAdjustment, timeIncrement; - BOOL isTimeAdjustmentDisabled, ok; - if (has_getickcount64) - info->implementation = "GetTickCount64()"; - else - info->implementation = "GetTickCount()"; - info->monotonic = 1; - ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, - &isTimeAdjustmentDisabled); - if (!ok) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - info->resolution = timeIncrement * 1e-7; - info->adjustable = 0; - } - return PyFloat_FromDouble(result); - -#elif defined(__APPLE__) - static mach_timebase_info_data_t timebase; - uint64_t time; - double secs; - - if (timebase.denom == 0) { - /* According to the Technical Q&A QA1398, mach_timebase_info() cannot - fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ - (void)mach_timebase_info(&timebase); - } - - time = mach_absolute_time(); - secs = (double)time * timebase.numer / timebase.denom * 1e-9; - if (info) { - info->implementation = "mach_absolute_time()"; - info->resolution = (double)timebase.numer / timebase.denom * 1e-9; - info->monotonic = 1; - info->adjustable = 0; - } - return PyFloat_FromDouble(secs); - -#elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC)) - struct timespec tp; -#ifdef CLOCK_HIGHRES - const clockid_t clk_id = CLOCK_HIGHRES; - const char *function = "clock_gettime(CLOCK_HIGHRES)"; -#else - const clockid_t clk_id = CLOCK_MONOTONIC; - const char *function = "clock_gettime(CLOCK_MONOTONIC)"; -#endif - - if (clock_gettime(clk_id, &tp) != 0) { - PyErr_SetFromErrno(PyExc_OSError); + _PyTime_timeval tv; + if (_PyTime_monotonic_info(&tv, info) < 0) { + assert(info != NULL); return NULL; } - - if (info) { - struct timespec res; - info->monotonic = 1; - info->implementation = function; - info->adjustable = 0; - if (clock_getres(clk_id, &res) == 0) - info->resolution = res.tv_sec + res.tv_nsec * 1e-9; - else - info->resolution = 1e-9; - } - return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); -#endif + return PyFloat_FromDouble((double)tv.tv_sec + tv.tv_usec * 1e-6); } static PyObject * @@ -1027,7 +916,6 @@ PyDoc_STRVAR(monotonic_doc, "monotonic() -> float\n\ \n\ Monotonic clock, cannot go backward."); -#endif /* PYMONOTONIC */ static PyObject* perf_counter(_Py_clock_info_t *info) @@ -1035,20 +923,7 @@ perf_counter(_Py_clock_info_t *info) #ifdef WIN32_PERF_COUNTER return win_perf_counter(info); #else - -#ifdef PYMONOTONIC - static int use_monotonic = 1; - - if (use_monotonic) { - PyObject *res = pymonotonic(info); - if (res != NULL) - return res; - use_monotonic = 0; - PyErr_Clear(); - } -#endif - return floattime(info); - + return pymonotonic(info); #endif } @@ -1216,10 +1091,8 @@ time_get_clock_info(PyObject *self, PyObject *args) else if (strcmp(name, "clock") == 0) obj = pyclock(&info); #endif -#ifdef PYMONOTONIC else if (strcmp(name, "monotonic") == 0) obj = pymonotonic(&info); -#endif else if (strcmp(name, "perf_counter") == 0) obj = perf_counter(&info); else if (strcmp(name, "process_time") == 0) @@ -1411,9 +1284,7 @@ static PyMethodDef time_methods[] = { #ifdef HAVE_WORKING_TZSET {"tzset", time_tzset, METH_NOARGS, tzset_doc}, #endif -#ifdef PYMONOTONIC {"monotonic", time_monotonic, METH_NOARGS, monotonic_doc}, -#endif {"process_time", time_process_time, METH_NOARGS, process_time_doc}, {"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc}, {"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc}, |