summaryrefslogtreecommitdiff
path: root/Modules/timemodule.c
diff options
context:
space:
mode:
authorAntoine Pitrou <pitrou@free.fr>2017-11-15 22:52:21 +0100
committerGitHub <noreply@github.com>2017-11-15 22:52:21 +0100
commit4bd41c9b52ea0c730e9e294caaf003e54c088c6e (patch)
tree9bb2c82cd67af88b9a3990ef081dd4b2c2f668c8 /Modules/timemodule.c
parent762b9571c9c8c6b036f1bf90140a1d030b3f9a01 (diff)
downloadcpython-git-4bd41c9b52ea0c730e9e294caaf003e54c088c6e.tar.gz
bpo-32025: Add time.thread_time() (#4410)
* bpo-32025: Add time.thread_time() * Add missing #endif * Add NEWS blurb * Add docs and whatsnew * Address review comments * Review comments
Diffstat (limited to 'Modules/timemodule.c')
-rw-r--r--Modules/timemodule.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 37abeb9507..5cae03dd41 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -1258,6 +1258,112 @@ Process time for profiling as nanoseconds:\n\
sum of the kernel and user-space CPU time.");
+#if defined(MS_WINDOWS)
+#define HAVE_THREAD_TIME
+static int
+_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+{
+ HANDLE thread;
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+ ULARGE_INTEGER large;
+ _PyTime_t ktime, utime, t;
+ BOOL ok;
+
+ thread = GetCurrentThread();
+ ok = GetThreadTimes(thread, &creation_time, &exit_time,
+ &kernel_time, &user_time);
+ if (!ok) {
+ PyErr_SetFromWindowsErr(0);
+ return -1;
+ }
+
+ if (info) {
+ info->implementation = "GetThreadTimes()";
+ info->resolution = 1e-7;
+ info->monotonic = 1;
+ info->adjustable = 0;
+ }
+
+ large.u.LowPart = kernel_time.dwLowDateTime;
+ large.u.HighPart = kernel_time.dwHighDateTime;
+ ktime = large.QuadPart;
+
+ large.u.LowPart = user_time.dwLowDateTime;
+ large.u.HighPart = user_time.dwHighDateTime;
+ utime = large.QuadPart;
+
+ /* ktime and utime have a resolution of 100 nanoseconds */
+ t = _PyTime_FromNanoseconds((ktime + utime) * 100);
+ *tp = t;
+ return 0;
+}
+
+#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
+#define HAVE_THREAD_TIME
+static int
+_PyTime_GetThreadTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info)
+{
+ struct timespec ts;
+ const clockid_t clk_id = CLOCK_THREAD_CPUTIME_ID;
+ const char *function = "clock_gettime(CLOCK_THREAD_CPUTIME_ID)";
+
+ if (clock_gettime(clk_id, &ts)) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ if (info) {
+ struct timespec res;
+ info->implementation = function;
+ info->monotonic = 1;
+ info->adjustable = 0;
+ if (clock_getres(clk_id, &res)) {
+ PyErr_SetFromErrno(PyExc_OSError);
+ return -1;
+ }
+ info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
+ }
+
+ if (_PyTime_FromTimespec(tp, &ts) < 0) {
+ return -1;
+ }
+ return 0;
+}
+#endif
+
+#ifdef HAVE_THREAD_TIME
+static PyObject *
+time_thread_time(PyObject *self, PyObject *unused)
+{
+ _PyTime_t t;
+ if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
+ return NULL;
+ }
+ return _PyFloat_FromPyTime(t);
+}
+
+PyDoc_STRVAR(thread_time_doc,
+"thread_time() -> float\n\
+\n\
+Thread time for profiling: sum of the kernel and user-space CPU time.");
+
+static PyObject *
+time_thread_time_ns(PyObject *self, PyObject *unused)
+{
+ _PyTime_t t;
+ if (_PyTime_GetThreadTimeWithInfo(&t, NULL) < 0) {
+ return NULL;
+ }
+ return _PyTime_AsNanosecondsObject(t);
+}
+
+PyDoc_STRVAR(thread_time_ns_doc,
+"thread_time() -> int\n\
+\n\
+Thread time for profiling as nanoseconds:\n\
+sum of the kernel and user-space CPU time.");
+#endif
+
+
static PyObject *
time_get_clock_info(PyObject *self, PyObject *args)
{
@@ -1311,6 +1417,13 @@ time_get_clock_info(PyObject *self, PyObject *args)
return NULL;
}
}
+#ifdef HAVE_THREAD_TIME
+ else if (strcmp(name, "thread_time") == 0) {
+ if (_PyTime_GetThreadTimeWithInfo(&t, &info) < 0) {
+ return NULL;
+ }
+ }
+#endif
else {
PyErr_SetString(PyExc_ValueError, "unknown clock");
return NULL;
@@ -1519,6 +1632,10 @@ static PyMethodDef time_methods[] = {
{"monotonic_ns", time_monotonic_ns, METH_NOARGS, monotonic_ns_doc},
{"process_time", time_process_time, METH_NOARGS, process_time_doc},
{"process_time_ns", time_process_time_ns, METH_NOARGS, process_time_ns_doc},
+#ifdef HAVE_THREAD_TIME
+ {"thread_time", time_thread_time, METH_NOARGS, thread_time_doc},
+ {"thread_time_ns", time_thread_time_ns, METH_NOARGS, thread_time_ns_doc},
+#endif
{"perf_counter", time_perf_counter, METH_NOARGS, perf_counter_doc},
{"perf_counter_ns", time_perf_counter_ns, METH_NOARGS, perf_counter_ns_doc},
{"get_clock_info", time_get_clock_info, METH_VARARGS, get_clock_info_doc},