diff options
| author | shadchin <[email protected]> | 2026-02-03 21:59:07 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2026-02-03 22:28:51 +0300 |
| commit | bce46f28de392862d5c6c3b185d844ee7c623be3 (patch) | |
| tree | 424878b5b90144f98970ce4a2745990c77330ad2 /contrib/tools/python3/Python/thread_pthread.h | |
| parent | 0e0ee9fa48ce9411b4038aa769493d22ff6c10a2 (diff) | |
Import Python 3.13.11
commit_hash:bbb53cefb159aa3e7afaa475fd19d5a03b66945f
Diffstat (limited to 'contrib/tools/python3/Python/thread_pthread.h')
| -rw-r--r-- | contrib/tools/python3/Python/thread_pthread.h | 143 |
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)); |
