summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Python/thread_pthread.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tools/python3/Python/thread_pthread.h')
-rw-r--r--contrib/tools/python3/Python/thread_pthread.h143
1 files changed, 110 insertions, 33 deletions
diff --git a/contrib/tools/python3/Python/thread_pthread.h b/contrib/tools/python3/Python/thread_pthread.h
index d843d8d7fe0..6523117e5e5 100644
--- a/contrib/tools/python3/Python/thread_pthread.h
+++ b/contrib/tools/python3/Python/thread_pthread.h
@@ -1,4 +1,6 @@
-#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
+#include "pycore_interp.h" // _PyInterpreterState.threads.stacksize
+#include "pycore_pythread.h" // _POSIX_SEMAPHORES
+#include "pycore_time.h" // _PyTime_FromMicrosecondsClamup()
/* Posix threads interface */
@@ -14,13 +16,14 @@
#undef destructor
#endif
#include <signal.h>
+#include <unistd.h> /* pause(), also getthrid() on OpenBSD */
#if defined(__linux__)
# include <sys/syscall.h> /* syscall(SYS_gettid) */
#elif defined(__FreeBSD__)
# include <pthread_np.h> /* pthread_getthreadid_np() */
-#elif defined(__OpenBSD__)
-# include <unistd.h> /* getthrid() */
+#elif defined(__FreeBSD_kernel__)
+# include <sys/syscall.h> /* syscall(SYS_thr_self) */
#elif defined(_AIX)
# include <sys/thread.h> /* thread_self() */
#elif defined(__NetBSD__)
@@ -84,10 +87,10 @@
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so
we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
-#define HAVE_BROKEN_POSIX_SEMAPHORES
+# define HAVE_BROKEN_POSIX_SEMAPHORES
#else
-#include <semaphore.h>
-#include <errno.h>
+# include <semaphore.h>
+# include <errno.h>
#endif
#endif
@@ -150,16 +153,18 @@ _PyThread_cond_init(PyCOND_T *cond)
void
_PyThread_cond_after(long long us, struct timespec *abs)
{
- _PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
- _PyTime_t t;
+ PyTime_t timeout = _PyTime_FromMicrosecondsClamp(us);
+ PyTime_t t;
#ifdef CONDATTR_MONOTONIC
if (condattr_monotonic) {
- t = _PyTime_GetMonotonicClock();
+ // silently ignore error: cannot report error to the caller
+ (void)PyTime_MonotonicRaw(&t);
}
else
#endif
{
- t = _PyTime_GetSystemClock();
+ // silently ignore error: cannot report error to the caller
+ (void)PyTime_TimeRaw(&t);
}
t = _PyTime_Add(t, timeout);
_PyTime_AsTimespec_clamp(t, abs);
@@ -238,8 +243,8 @@ pythread_wrapper(void *arg)
return NULL;
}
-unsigned long
-PyThread_start_new_thread(void (*func)(void *), void *arg)
+static int
+do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id)
{
pthread_t th;
int status;
@@ -255,7 +260,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
if (pthread_attr_init(&attrs) != 0)
- return PYTHREAD_INVALID_THREAD_ID;
+ return -1;
#endif
#if defined(THREAD_STACK_SIZE)
PyThreadState *tstate = _PyThreadState_GET();
@@ -264,7 +269,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
if (tss != 0) {
if (pthread_attr_setstacksize(&attrs, tss) != 0) {
pthread_attr_destroy(&attrs);
- return PYTHREAD_INVALID_THREAD_ID;
+ return -1;
}
}
#endif
@@ -275,7 +280,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
pythread_callback *callback = PyMem_RawMalloc(sizeof(pythread_callback));
if (callback == NULL) {
- return PYTHREAD_INVALID_THREAD_ID;
+ return -1;
}
callback->func = func;
@@ -295,32 +300,83 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
if (status != 0) {
PyMem_RawFree(callback);
- return PYTHREAD_INVALID_THREAD_ID;
+ return -1;
}
+ *out_id = th;
+ return 0;
+}
- pthread_detach(th);
-
-#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
- return (unsigned long) th;
+/* Helper to convert pthread_t to PyThread_ident_t. POSIX allows pthread_t to be
+ non-arithmetic, e.g., musl typedefs it as a pointer. */
+static PyThread_ident_t
+_pthread_t_to_ident(pthread_t value) {
+// Cast through an integer type of the same size to avoid sign-extension.
+#if SIZEOF_PTHREAD_T == SIZEOF_VOID_P
+ return (uintptr_t) value;
+#elif SIZEOF_PTHREAD_T == SIZEOF_LONG
+ return (unsigned long) value;
+#elif SIZEOF_PTHREAD_T == SIZEOF_INT
+ return (unsigned int) value;
+#elif SIZEOF_PTHREAD_T == SIZEOF_LONG_LONG
+ return (unsigned long long) value;
#else
- return (unsigned long) *(unsigned long *) &th;
+#error "Unsupported SIZEOF_PTHREAD_T value"
#endif
}
+int
+PyThread_start_joinable_thread(void (*func)(void *), void *arg,
+ PyThread_ident_t* ident, PyThread_handle_t* handle) {
+ pthread_t th = (pthread_t) 0;
+ if (do_start_joinable_thread(func, arg, &th)) {
+ return -1;
+ }
+ *ident = _pthread_t_to_ident(th);
+ *handle = (PyThread_handle_t) th;
+ assert(th == (pthread_t) *handle);
+ return 0;
+}
+
+unsigned long
+PyThread_start_new_thread(void (*func)(void *), void *arg)
+{
+ pthread_t th = (pthread_t) 0;
+ if (do_start_joinable_thread(func, arg, &th)) {
+ return PYTHREAD_INVALID_THREAD_ID;
+ }
+ pthread_detach(th);
+ return (unsigned long) _pthread_t_to_ident(th);;
+}
+
+int
+PyThread_join_thread(PyThread_handle_t th) {
+ return pthread_join((pthread_t) th, NULL);
+}
+
+int
+PyThread_detach_thread(PyThread_handle_t th) {
+ return pthread_detach((pthread_t) th);
+}
+
/* XXX This implementation is considered (to quote Tim Peters) "inherently
hosed" because:
- It does not guarantee the promise that a non-zero integer is returned.
- The cast to unsigned long is inherently unsafe.
- It is not clear that the 'volatile' (for AIX?) are any longer necessary.
*/
-unsigned long
-PyThread_get_thread_ident(void)
-{
+PyThread_ident_t
+PyThread_get_thread_ident_ex(void) {
volatile pthread_t threadid;
if (!initialized)
PyThread_init_thread();
threadid = pthread_self();
- return (unsigned long) threadid;
+ return _pthread_t_to_ident(threadid);
+}
+
+unsigned long
+PyThread_get_thread_ident(void)
+{
+ return (unsigned long) PyThread_get_thread_ident_ex();
}
#ifdef PY_HAVE_THREAD_NATIVE_ID
@@ -338,6 +394,9 @@ PyThread_get_thread_native_id(void)
#elif defined(__FreeBSD__)
int native_id;
native_id = pthread_getthreadid_np();
+#elif defined(__FreeBSD_kernel__)
+ long native_id;
+ syscall(SYS_thr_self, &native_id);
#elif defined(__OpenBSD__)
pid_t native_id;
native_id = getthrid();
@@ -371,6 +430,18 @@ PyThread_exit_thread(void)
#endif
}
+void _Py_NO_RETURN
+PyThread_hang_thread(void)
+{
+ while (1) {
+#if defined(__wasi__)
+ sleep(9999999); // WASI doesn't have pause() ?!
+#else
+ pause();
+#endif
+ }
+}
+
#ifdef USE_SEMAPHORES
/*
@@ -440,31 +511,34 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
(void) error; /* silence unused-but-set-variable warning */
- _PyTime_t timeout; // relative timeout
+ PyTime_t timeout; // relative timeout
if (microseconds >= 0) {
// bpo-41710: PyThread_acquire_lock_timed() cannot report timeout
// overflow to the caller, so clamp the timeout to
- // [_PyTime_MIN, _PyTime_MAX].
+ // [PyTime_MIN, PyTime_MAX].
//
- // _PyTime_MAX nanoseconds is around 292.3 years.
+ // PyTime_MAX nanoseconds is around 292.3 years.
//
// _thread.Lock.acquire() and _thread.RLock.acquire() raise an
// OverflowError if microseconds is greater than PY_TIMEOUT_MAX.
timeout = _PyTime_FromMicrosecondsClamp(microseconds);
}
else {
- timeout = _PyTime_FromNanoseconds(-1);
+ timeout = -1;
}
#ifdef HAVE_SEM_CLOCKWAIT
struct timespec abs_timeout;
// Local scope for deadline
{
- _PyTime_t deadline = _PyTime_Add(_PyTime_GetMonotonicClock(), timeout);
+ PyTime_t now;
+ // silently ignore error: cannot report error to the caller
+ (void)PyTime_MonotonicRaw(&now);
+ PyTime_t deadline = _PyTime_Add(now, timeout);
_PyTime_AsTimespec_clamp(deadline, &abs_timeout);
}
#else
- _PyTime_t deadline = 0;
+ PyTime_t deadline = 0;
if (timeout > 0 && !intr_flag) {
deadline = _PyDeadline_Init(timeout);
}
@@ -476,8 +550,11 @@ PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
status = fix_status(sem_clockwait(thelock, CLOCK_MONOTONIC,
&abs_timeout));
#else
- _PyTime_t abs_time = _PyTime_Add(_PyTime_GetSystemClock(),
- timeout);
+ PyTime_t now;
+ // silently ignore error: cannot report error to the caller
+ (void)PyTime_TimeRaw(&now);
+ PyTime_t abs_time = _PyTime_Add(now, timeout);
+
struct timespec ts;
_PyTime_AsTimespec_clamp(abs_time, &ts);
status = fix_status(sem_timedwait(thelock, &ts));