#include "pycore_interp.h"
#include "pycore_pythread.h"
#include "pycore_time.h"
#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
#define destructor …
#endif
#ifndef HAVE_PTHREAD_STUBS
# include <pthread.h>
#endif
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
#undef destructor
#endif
#include <signal.h>
#include <unistd.h>
#if defined(__linux__)
# include <sys/syscall.h>
#elif defined(__FreeBSD__)
# include <pthread_np.h>
#elif defined(__FreeBSD_kernel__)
# include <sys/syscall.h>
#elif defined(_AIX)
# include <sys/thread.h>
#elif defined(__NetBSD__)
# include <lwp.h>
#elif defined(__DragonFly__)
# include <sys/lwp.h>
#endif
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
#ifndef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE …
#endif
#if defined(__FreeBSD__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
#undef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE …
#endif
#if defined(_AIX) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
#undef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE …
#endif
#if defined(__ANDROID__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
# ifdef Py_DEBUG
# undef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE …
# endif
#endif
#if defined(__VXWORKS__) && defined(THREAD_STACK_SIZE) && THREAD_STACK_SIZE == 0
#undef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE …
#endif
#define THREAD_STACK_MIN …
#else
#ifdef THREAD_STACK_SIZE
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
#endif
#endif
#ifdef _POSIX_SEMAPHORES
#if (_POSIX_SEMAPHORES+0) == -1
#define HAVE_BROKEN_POSIX_SEMAPHORES
#else
# include <semaphore.h>
# include <errno.h>
#endif
#endif
#ifdef _Py_THREAD_SANITIZER
#undef HAVE_SEM_CLOCKWAIT
#endif
#if (defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES) && \
(defined(HAVE_SEM_TIMEDWAIT) || defined(HAVE_SEM_CLOCKWAIT)))
#define USE_SEMAPHORES
#else
# undef USE_SEMAPHORES
#endif
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
#define SET_THREAD_SIGMASK …
#else
#define SET_THREAD_SIGMASK …
#endif
#define condattr_monotonic …
static void
init_condattr(void)
{ … }
int
_PyThread_cond_init(PyCOND_T *cond)
{ … }
void
_PyThread_cond_after(long long us, struct timespec *abs)
{ … }
pthread_lock;
#define CHECK_STATUS(name) …
#define CHECK_STATUS_PTHREAD(name) …
static void
PyThread__init_thread(void)
{ … }
pythread_callback;
static void *
pythread_wrapper(void *arg)
{ … }
static int
do_start_joinable_thread(void (*func)(void *), void *arg, pthread_t* out_id)
{ … }
int
PyThread_start_joinable_thread(void (*func)(void *), void *arg,
PyThread_ident_t* ident, PyThread_handle_t* handle) { … }
unsigned long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{ … }
int
PyThread_join_thread(PyThread_handle_t th) { … }
int
PyThread_detach_thread(PyThread_handle_t th) { … }
PyThread_ident_t
PyThread_get_thread_ident_ex(void) { … }
unsigned long
PyThread_get_thread_ident(void)
{ … }
#ifdef PY_HAVE_THREAD_NATIVE_ID
unsigned long
PyThread_get_thread_native_id(void)
{ … }
#endif
void _Py_NO_RETURN
PyThread_exit_thread(void)
{ … }
void _Py_NO_RETURN
PyThread_hang_thread(void)
{ … }
#ifdef USE_SEMAPHORES
PyThread_type_lock
PyThread_allocate_lock(void)
{ … }
void
PyThread_free_lock(PyThread_type_lock lock)
{ … }
static int
fix_status(int status)
{ … }
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
int intr_flag)
{ … }
void
PyThread_release_lock(PyThread_type_lock lock)
{ … }
#else
PyThread_type_lock
PyThread_allocate_lock(void)
{
pthread_lock *lock;
int status, error = 0;
if (!initialized)
PyThread_init_thread();
lock = (pthread_lock *) PyMem_RawCalloc(1, sizeof(pthread_lock));
if (lock) {
lock->locked = 0;
status = pthread_mutex_init(&lock->mut, NULL);
CHECK_STATUS_PTHREAD("pthread_mutex_init");
_Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&lock->mut);
status = _PyThread_cond_init(&lock->lock_released);
CHECK_STATUS_PTHREAD("pthread_cond_init");
if (error) {
PyMem_RawFree((void *)lock);
lock = 0;
}
}
return (PyThread_type_lock) lock;
}
void
PyThread_free_lock(PyThread_type_lock lock)
{
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
(void) error;
status = pthread_cond_destroy( &thelock->lock_released );
CHECK_STATUS_PTHREAD("pthread_cond_destroy");
status = pthread_mutex_destroy( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_destroy");
PyMem_RawFree((void *)thelock);
}
PyLockStatus
PyThread_acquire_lock_timed(PyThread_type_lock lock, PY_TIMEOUT_T microseconds,
int intr_flag)
{
PyLockStatus success = PY_LOCK_FAILURE;
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
if (microseconds == 0) {
status = pthread_mutex_trylock( &thelock->mut );
if (status != EBUSY) {
CHECK_STATUS_PTHREAD("pthread_mutex_trylock[1]");
}
}
else {
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_lock[1]");
}
if (status != 0) {
goto done;
}
if (thelock->locked == 0) {
success = PY_LOCK_ACQUIRED;
goto unlock;
}
if (microseconds == 0) {
goto unlock;
}
struct timespec abs_timeout;
if (microseconds > 0) {
_PyThread_cond_after(microseconds, &abs_timeout);
}
while (1) {
if (microseconds > 0) {
status = pthread_cond_timedwait(&thelock->lock_released,
&thelock->mut, &abs_timeout);
if (status == 1) {
break;
}
if (status == ETIMEDOUT) {
break;
}
CHECK_STATUS_PTHREAD("pthread_cond_timedwait");
}
else {
status = pthread_cond_wait(
&thelock->lock_released,
&thelock->mut);
CHECK_STATUS_PTHREAD("pthread_cond_wait");
}
if (intr_flag && status == 0 && thelock->locked) {
success = PY_LOCK_INTR;
break;
}
if (status == 0 && !thelock->locked) {
success = PY_LOCK_ACQUIRED;
break;
}
}
unlock:
if (success == PY_LOCK_ACQUIRED) {
thelock->locked = 1;
}
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_unlock[1]");
done:
if (error) {
success = PY_LOCK_FAILURE;
}
return success;
}
void
PyThread_release_lock(PyThread_type_lock lock)
{
pthread_lock *thelock = (pthread_lock *)lock;
int status, error = 0;
(void) error;
status = pthread_mutex_lock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_lock[3]");
thelock->locked = 0;
status = pthread_cond_signal( &thelock->lock_released );
CHECK_STATUS_PTHREAD("pthread_cond_signal");
status = pthread_mutex_unlock( &thelock->mut );
CHECK_STATUS_PTHREAD("pthread_mutex_unlock[3]");
}
#endif
int
_PyThread_at_fork_reinit(PyThread_type_lock *lock)
{ … }
int
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{ … }
static int
_pythread_pthread_set_stacksize(size_t size)
{ … }
#define THREAD_SET_STACKSIZE(x) …
int
PyThread_create_key(void)
{ … }
void
PyThread_delete_key(int key)
{ … }
void
PyThread_delete_key_value(int key)
{ … }
int
PyThread_set_key_value(int key, void *value)
{ … }
void *
PyThread_get_key_value(int key)
{ … }
void
PyThread_ReInitTLS(void)
{ … }
int
PyThread_tss_create(Py_tss_t *key)
{ … }
void
PyThread_tss_delete(Py_tss_t *key)
{ … }
int
PyThread_tss_set(Py_tss_t *key, void *value)
{ … }
void *
PyThread_tss_get(Py_tss_t *key)
{ … }