diff options
Diffstat (limited to 'Modules/timemodule.c')
-rw-r--r-- | Modules/timemodule.c | 235 |
1 files changed, 26 insertions, 209 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c index d0917a4073..7f5f3149af 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -27,28 +27,13 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include "pythread.h" - -#if defined(__BORLANDC__) -/* These overrides not needed for Win32 */ -#define timezone _timezone -#define tzname _tzname -#define daylight _daylight -#endif /* __BORLANDC__ */ #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); -#ifdef MS_WINDOWS -static OSVERSIONINFOEX winver; -#endif - static PyObject * time_time(PyObject *self, PyObject *unused) { @@ -92,12 +77,12 @@ floatclock(_Py_clock_info_t *info) } #endif /* HAVE_CLOCK */ -#if defined(MS_WINDOWS) && !defined(__BORLANDC__) +#ifdef MS_WINDOWS #define WIN32_PERF_COUNTER /* Win32 has better clock replacement; we have our own version, due to Mark Hammond and Tim Peters */ -static int -win_perf_counter(_Py_clock_info_t *info, PyObject **result) +static PyObject* +win_perf_counter(_Py_clock_info_t *info) { static LONGLONG cpu_frequency = 0; static LONGLONG ctrStart; @@ -109,10 +94,8 @@ win_perf_counter(_Py_clock_info_t *info, PyObject **result) QueryPerformanceCounter(&now); ctrStart = now.QuadPart; if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) { - /* Unlikely to happen - this works on all intel - machines at least! Revert to clock() */ - *result = NULL; - return -1; + PyErr_SetFromWindowsErr(0); + return NULL; } cpu_frequency = freq.QuadPart; } @@ -124,10 +107,9 @@ win_perf_counter(_Py_clock_info_t *info, PyObject **result) info->monotonic = 1; info->adjustable = 0; } - *result = PyFloat_FromDouble(diff / (double)cpu_frequency); - return 0; + return PyFloat_FromDouble(diff / (double)cpu_frequency); } -#endif +#endif /* MS_WINDOWS */ #if defined(WIN32_PERF_COUNTER) || defined(HAVE_CLOCK) #define PYCLOCK @@ -135,11 +117,10 @@ static PyObject* pyclock(_Py_clock_info_t *info) { #ifdef WIN32_PERF_COUNTER - PyObject *res; - if (win_perf_counter(info, &res) == 0) - return res; -#endif + return win_perf_counter(info); +#else return floatclock(info); +#endif } static PyObject * @@ -169,7 +150,7 @@ time_clock_gettime(PyObject *self, PyObject *args) ret = clock_gettime((clockid_t)clk_id, &tp); if (ret != 0) { - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); return NULL; } return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); @@ -200,7 +181,7 @@ time_clock_settime(PyObject *self, PyObject *args) ret = clock_settime((clockid_t)clk_id, &tp); if (ret != 0) { - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); return NULL; } Py_RETURN_NONE; @@ -223,7 +204,7 @@ time_clock_getres(PyObject *self, PyObject *args) ret = clock_getres((clockid_t)clk_id, &tp); if (ret != 0) { - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); return NULL; } @@ -903,122 +884,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 * @@ -1031,40 +905,15 @@ PyDoc_STRVAR(monotonic_doc, "monotonic() -> float\n\ \n\ Monotonic clock, cannot go backward."); -#endif /* PYMONOTONIC */ static PyObject* perf_counter(_Py_clock_info_t *info) { -#if defined(WIN32_PERF_COUNTER) || defined(PYMONOTONIC) - PyObject *res; -#endif -#if defined(WIN32_PERF_COUNTER) - static int use_perf_counter = 1; -#endif -#ifdef PYMONOTONIC - static int use_monotonic = 1; -#endif - #ifdef WIN32_PERF_COUNTER - if (use_perf_counter) { - if (win_perf_counter(info, &res) == 0) - return res; - use_perf_counter = 0; - } -#endif - -#ifdef PYMONOTONIC - if (use_monotonic) { - res = pymonotonic(info); - if (res != NULL) - return res; - use_monotonic = 0; - PyErr_Clear(); - } + return win_perf_counter(info); +#else + return pymonotonic(info); #endif - - return floattime(info); } static PyObject * @@ -1231,10 +1080,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) @@ -1426,9 +1273,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}, @@ -1510,15 +1355,6 @@ PyInit_time(void) if (PyStructSequence_InitType2(&StructTimeType, &struct_time_type_desc) < 0) return NULL; - -#ifdef MS_WINDOWS - winver.dwOSVersionInfoSize = sizeof(winver); - if (!GetVersionEx((OSVERSIONINFO*)&winver)) { - Py_DECREF(m); - PyErr_SetFromWindowsErr(0); - return NULL; - } -#endif } Py_INCREF(&StructTimeType); #ifdef HAVE_STRUCT_TM_TM_ZONE @@ -1535,29 +1371,10 @@ static PyObject* floattime(_Py_clock_info_t *info) { _PyTime_timeval t; -#ifdef HAVE_CLOCK_GETTIME - struct timespec tp; - int ret; - - /* _PyTime_gettimeofday() does not use clock_gettime() - because it would require to link Python to the rt (real-time) - library, at least on Linux */ - ret = clock_gettime(CLOCK_REALTIME, &tp); - if (ret == 0) { - if (info) { - struct timespec res; - info->implementation = "clock_gettime(CLOCK_REALTIME)"; - info->monotonic = 0; - info->adjustable = 1; - if (clock_getres(CLOCK_REALTIME, &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); + if (_PyTime_gettimeofday_info(&t, info) < 0) { + assert(info != NULL); + return NULL; } -#endif - _PyTime_gettimeofday_info(&t, info); return PyFloat_FromDouble((double)t.tv_sec + t.tv_usec * 1e-6); } @@ -1591,7 +1408,7 @@ floatsleep(double secs) else #endif { - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); return -1; } } @@ -1625,7 +1442,7 @@ floatsleep(double secs) if (rc == WAIT_OBJECT_0) { Py_BLOCK_THREADS errno = EINTR; - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); return -1; } } |