Skip to content

bpo-31596: Add an interface for pthread_getcpuclockid(3) #3756

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Doc/library/time.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ The module defines the following functions and data items:
:func:`perf_counter` or :func:`process_time` instead, depending on your
requirements, to have a well defined behaviour.

.. function:: pthread_getcpuclockid(thread_id)

Return the *clk_id* of the thread-specific CPU-time clock for the specified *thread_id*.

Use :func:`threading.get_ident` or the :attr:`~threading.Thread.ident`
attribute of :class:`threading.Thread` objects to get a suitable value
for *thread_id*.

.. warning::
Passing an invalid or expired *thread_id* may result in
undefined behavior, such as segmentation fault.

Availability: Unix (see the man page for :manpage:`pthread_getcpuclockid(3)` for
further information)

.. versionadded:: 3.7

.. function:: clock_getres(clk_id)

Expand Down
20 changes: 20 additions & 0 deletions Lib/test/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import sys
import sysconfig
import time
import threading
import unittest
try:
import _testcapi
Expand Down Expand Up @@ -80,6 +81,25 @@ def test_clock_monotonic(self):
b = time.clock_gettime(time.CLOCK_MONOTONIC)
self.assertLessEqual(a, b)

@unittest.skipUnless(hasattr(time, 'pthread_getcpuclockid'),
'need time.pthread_getcpuclockid()')
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
@unittest.skipUnless(hasattr(time, 'CLOCK_THREAD_CPUTIME_ID'),
'need time.CLOCK_THREAD_CPUTIME_ID')
def test_pthread_getcpuclockid(self):
clk_id = time.pthread_getcpuclockid(threading.get_ident())
self.assertTrue(type(clk_id) is int)
self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID)
# This should suffice to show that both calls are measuring the same clock.
t1 = time.clock_gettime(clk_id)
t2 = time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID)
t3 = time.clock_gettime(clk_id)
t4 = time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID)
self.assertLessEqual(t1, t2)
self.assertLessEqual(t2, t3)
self.assertLessEqual(t3, t4)

@unittest.skipUnless(hasattr(time, 'clock_getres'),
'need time.clock_getres()')
def test_clock_getres(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added pthread_getcpuclockid() to the time module
32 changes: 32 additions & 0 deletions Modules/timemodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include <io.h>
#endif

#if defined(HAVE_PTHREAD_H)
# include <pthread.h>
#endif

#if defined(__WATCOMC__) && !defined(__QNX__)
#include <i86.h>
#else
Expand Down Expand Up @@ -221,6 +225,31 @@ PyDoc_STRVAR(clock_getres_doc,
Return the resolution (precision) of the specified clock clk_id.");
#endif /* HAVE_CLOCK_GETRES */

#ifdef HAVE_PTHREAD_GETCPUCLOCKID
static PyObject *
time_pthread_getcpuclockid(PyObject *self, PyObject *args)
{
unsigned long thread_id;
int err;
clockid_t clk_id;
if (!PyArg_ParseTuple(args, "k:pthread_getcpuclockid", &thread_id)) {
return NULL;
}
err = pthread_getcpuclockid((pthread_t)thread_id, &clk_id);
if (err) {
errno = err;
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return PyLong_FromLong(clk_id);
}

PyDoc_STRVAR(pthread_getcpuclockid_doc,
"pthread_getcpuclockid(thread_id) -> int\n\
\n\
Return the clk_id of a thread's CPU time clock.");
#endif /* HAVE_PTHREAD_GETCPUCLOCKID */

static PyObject *
time_sleep(PyObject *self, PyObject *obj)
{
Expand Down Expand Up @@ -1287,6 +1316,9 @@ static PyMethodDef time_methods[] = {
#endif
#ifdef HAVE_CLOCK_GETRES
{"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
#endif
#ifdef HAVE_PTHREAD_GETCPUCLOCKID
{"pthread_getcpuclockid", time_pthread_getcpuclockid, METH_VARARGS, pthread_getcpuclockid_doc},
#endif
{"sleep", time_sleep, METH_O, sleep_doc},
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
Expand Down
11 changes: 11 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -10585,6 +10585,17 @@ if test "x$ac_cv_func_pthread_atfork" = xyes; then :
#define HAVE_PTHREAD_ATFORK 1
_ACEOF

fi
done

for ac_func in pthread_getcpuclockid
do :
ac_fn_c_check_func "$LINENO" "pthread_getcpuclockid" "ac_cv_func_pthread_getcpuclockid"
if test "x$ac_cv_func_pthread_getcpuclockid" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_PTHREAD_GETCPUCLOCKID 1
_ACEOF

fi
done

Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3038,6 +3038,7 @@ if test "$posix_threads" = "yes"; then
;;
esac])
AC_CHECK_FUNCS(pthread_atfork)
AC_CHECK_FUNCS(pthread_getcpuclockid)
fi


Expand Down
3 changes: 3 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,9 @@
/* Defined for Solaris 2.6 bug in pthread header. */
#undef HAVE_PTHREAD_DESTRUCTOR

/* Define to 1 if you have the `pthread_getcpuclockid' function. */
#undef HAVE_PTHREAD_GETCPUCLOCKID

/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H

Expand Down