diff --git a/Modules/timemodule.c b/Modules/timemodule.c
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -40,6 +40,19 @@
#include
#endif
+#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
+# define HAVE_PYCLOCK
+#endif
+
+#ifdef HAVE_CLOCK_GETTIME
+typedef struct timespec _PyTime_timespec;
+#else
+typedef struct {
+ time_t tv_sec; /* seconds since Jan. 1, 1970 */
+ long tv_nsec; /* and nanoseconds */
+} _PyTime_timespec;
+#endif
+
/* Forward declarations */
static int floatsleep(double);
static double floattime(void);
@@ -56,6 +69,7 @@ time_time(PyObject *self, PyObject *unus
return PyFloat_FromDouble(secs);
}
+
PyDoc_STRVAR(time_doc,
"time() -> floating point number\n\
\n\
@@ -63,34 +77,49 @@ Return the current time in seconds since
Fractions of a second may be present if the system clock provides them.");
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
+typedef LARGE_INTEGER pyclock_t;
+
/* Win32 has better clock replacement; we have our own version, due to Mark
Hammond and Tim Peters */
-static PyObject *
-time_clock(PyObject *self, PyObject *unused)
+static int
+pyclock(pyclock_t *value, pyclock_t *divisor)
{
static LARGE_INTEGER ctrStart;
- static double divisor = 0.0;
+ static LARGE_INTEGER cpu_frequency = 0;
LARGE_INTEGER now;
double diff;
- if (divisor == 0.0) {
+ if (cpu_frequency == 0) {
LARGE_INTEGER freq;
QueryPerformanceCounter(&ctrStart);
- if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) {
+ if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0)
+ {
/* Unlikely to happen - this works on all intel
machines at least! Revert to clock() */
- return PyFloat_FromDouble(((double)clock()) /
- CLOCKS_PER_SEC);
+ clock_t processor_time;
+ processor_time = clock();
+ if (processor_time == (clock_t)-1) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "the processor time used is not available "
+ "or its value cannot be represented");
+ return -1;
+ }
+ *value = processor_time;
+ *divisor = CLOCKS_PER_SEC;
+ return 0;
}
- divisor = (double)freq.QuadPart;
+ cpu_frequency = freq.QuadPart;
}
QueryPerformanceCounter(&now);
- diff = (double)(now.QuadPart - ctrStart.QuadPart);
- return PyFloat_FromDouble(diff / divisor);
+ *value = now.QuadPart - ctrStart.QuadPart;
+ *divisor = cpu_frequency;
+ return 0;
}
#elif defined(HAVE_CLOCK)
+typedef clock_t pyclock_t;
+
#ifndef CLOCKS_PER_SEC
#ifdef CLK_TCK
#define CLOCKS_PER_SEC CLK_TCK
@@ -99,13 +128,33 @@ time_clock(PyObject *self, PyObject *unu
#endif
#endif
+static int
+pyclock(pyclock_t *value, pyclock_t *divisor)
+{
+ clock_t processor_time;
+ processor_time = clock();
+ if (processor_time == (clock_t)-1) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "the processor time used is not available "
+ "or its value cannot be represented");
+ return -1;
+ }
+ *value = processor_time;
+ *divisor = CLOCKS_PER_SEC;
+ return 0;
+}
+#endif /* HAVE_CLOCK */
+
+#ifdef HAVE_PYCLOCK
static PyObject *
time_clock(PyObject *self, PyObject *unused)
{
- return PyFloat_FromDouble(((double)clock()) / CLOCKS_PER_SEC);
+ pyclock_t value, divisor;
+ if (pyclock(&value, &divisor))
+ return NULL;
+ return PyFloat_FromDouble((double)value / (double)divisor);
}
-#endif /* HAVE_CLOCK */
-
+#endif
#ifdef HAVE_CLOCK
PyDoc_STRVAR(clock_doc,
@@ -737,12 +786,28 @@ the local timezone used by methods such
should not be relied on.");
#endif /* HAVE_WORKING_TZSET */
-static PyObject *
-time_wallclock(PyObject *self, PyObject *unused)
+static int
+pywallclock(_PyTime_timespec *ts)
{
#if defined(MS_WINDOWS) && !defined(__BORLANDC__)
- return time_clock(self, NULL);
-#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+ pyclock_t value, divisor;
+ unsigned long k;
+#define NANOSEC 1000000000
+ if (pyclock(&value, &divisor))
+ return -1;
+ ts->tv_sec = value / divisor;
+ if (NANOSEC >= divisor) {
+ k = NANOSEC / divisor;
+ ts->tv_nsec = (value % divisor) * k;
+ }
+ else {
+ k = divisor / NANOSEC;
+ ts->tv_nsec = (value % divisor) / k;
+ }
+ return 0;
+#else
+
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
static int clk_index = 0;
clockid_t clk_ids[] = {
#ifdef CLOCK_MONOTONIC_RAW
@@ -762,18 +827,34 @@ time_wallclock(PyObject *self, PyObject
clockid_t clk_id = clk_ids[clk_index];
ret = clock_gettime(clk_id, &tp);
if (ret == 0)
- return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
+ {
+ ts->tv_sec = tp.tv_sec;
+ ts->tv_nsec = tp.tv_nsec;
+ return 0;
+ }
clk_index++;
if (Py_ARRAY_LENGTH(clk_ids) <= clk_index)
clk_index = -1;
}
- return time_time(self, NULL);
-#else
- return time_time(self, NULL);
+#endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) */
+ _PyTime_timeval t;
+ _PyTime_gettimeofday(&t);
+ ts->tv_sec = t.tv_sec;
+ ts->tv_nsec = t.tv_usec * 1000;
+ return 0;
#endif
}
+static PyObject *
+time_wallclock(PyObject *self, PyObject *unused)
+{
+ _PyTime_timespec ts;
+ if (pywallclock(&ts))
+ return NULL;
+ return PyFloat_FromDouble(ts.tv_sec + ts.tv_nsec * 1e-9);
+}
+
PyDoc_STRVAR(wallclock_doc,
"wallclock() -> float\n\
\n\
@@ -894,7 +975,7 @@ PyInit_timezone(PyObject *m) {
static PyMethodDef time_methods[] = {
{"time", time_time, METH_NOARGS, time_doc},
-#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
+#ifdef HAVE_PYCLOCK
{"clock", time_clock, METH_NOARGS, clock_doc},
#endif
#ifdef HAVE_CLOCK_GETTIME