1 #ifndef Py_INTERNAL_PYTHREAD_H 2 #define Py_INTERNAL_PYTHREAD_H 3 #ifdef __cplusplus 4 extern "C" { 5 #endif 6 7 #ifndef Py_BUILD_CORE 8 # error "this header requires Py_BUILD_CORE define" 9 #endif 10 11 #include "dynamic_annotations.h" // _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX 12 #include "pycore_llist.h" // struct llist_node 13 14 // Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available 15 #if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \ 16 && !defined(_POSIX_SEMAPHORES)) 17 # include <unistd.h> // _POSIX_THREADS, _POSIX_SEMAPHORES 18 #endif 19 #if (defined(HAVE_PTHREAD_H) && !defined(_POSIX_THREADS) \ 20 && !defined(_POSIX_SEMAPHORES)) 21 // This means pthreads are not implemented in libc headers, hence the macro 22 // not present in <unistd.h>. But they still can be implemented as an 23 // external library (e.g. gnu pth in pthread emulation) 24 # include <pthread.h> // _POSIX_THREADS, _POSIX_SEMAPHORES 25 #endif 26 #if !defined(_POSIX_THREADS) && defined(__hpux) && defined(_SC_THREADS) 27 // Check if we're running on HP-UX and _SC_THREADS is defined. If so, then 28 // enough of the POSIX threads package is implemented to support Python 29 // threads. 30 // 31 // This is valid for HP-UX 11.23 running on an ia64 system. If needed, add 32 // a check of __ia64 to verify that we're running on an ia64 system instead 33 // of a pa-risc system. 34 # define _POSIX_THREADS 35 #endif 36 37 38 #if defined(_POSIX_THREADS) || defined(HAVE_PTHREAD_STUBS) 39 # define _USE_PTHREADS 40 #endif 41 42 #if defined(_USE_PTHREADS) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) 43 // monotonic is supported statically. It doesn't mean it works on runtime. 44 # define CONDATTR_MONOTONIC 45 #endif 46 47 48 #if defined(HAVE_PTHREAD_STUBS) 49 #include "cpython/pthread_stubs.h" // PTHREAD_KEYS_MAX 50 #include <stdbool.h> // bool 51 52 // pthread_key 53 struct py_stub_tls_entry { 54 bool in_use; 55 void *value; 56 }; 57 #endif 58 59 struct _pythread_runtime_state { 60 int initialized; 61 62 #ifdef _USE_PTHREADS 63 // This matches when thread_pthread.h is used. 64 struct { 65 /* NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported. */ 66 pthread_condattr_t *ptr; 67 # ifdef CONDATTR_MONOTONIC 68 /* The value to which condattr_monotonic is set. */ 69 pthread_condattr_t val; 70 # endif 71 } _condattr_monotonic; 72 73 #endif // USE_PTHREADS 74 75 #if defined(HAVE_PTHREAD_STUBS) 76 struct { 77 struct py_stub_tls_entry tls_entries[PTHREAD_KEYS_MAX]; 78 } stubs; 79 #endif 80 81 // Linked list of ThreadHandles 82 struct llist_node handles; 83 }; 84 85 #define _pythread_RUNTIME_INIT(pythread) \ 86 { \ 87 .handles = LLIST_INIT(pythread.handles), \ 88 } 89 90 #ifdef HAVE_FORK 91 /* Private function to reinitialize a lock at fork in the child process. 92 Reset the lock to the unlocked state. 93 Return 0 on success, return -1 on error. */ 94 extern int _PyThread_at_fork_reinit(PyThread_type_lock *lock); 95 extern void _PyThread_AfterFork(struct _pythread_runtime_state *state); 96 #endif /* HAVE_FORK */ 97 98 99 // unset: -1 seconds, in nanoseconds 100 #define PyThread_UNSET_TIMEOUT ((PyTime_t)(-1 * 1000 * 1000 * 1000)) 101 102 // Exported for the _interpchannels module. 103 PyAPI_FUNC(int) PyThread_ParseTimeoutArg( 104 PyObject *arg, 105 int blocking, 106 PY_TIMEOUT_T *timeout); 107 108 /* Helper to acquire an interruptible lock with a timeout. If the lock acquire 109 * is interrupted, signal handlers are run, and if they raise an exception, 110 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE 111 * are returned, depending on whether the lock can be acquired within the 112 * timeout. 113 */ 114 // Exported for the _interpchannels module. 115 PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries( 116 PyThread_type_lock, 117 PY_TIMEOUT_T microseconds); 118 119 typedef unsigned long long PyThread_ident_t; 120 typedef Py_uintptr_t PyThread_handle_t; 121 122 #define PY_FORMAT_THREAD_IDENT_T "llu" 123 #define Py_PARSE_THREAD_IDENT_T "K" 124 125 PyAPI_FUNC(PyThread_ident_t) PyThread_get_thread_ident_ex(void); 126 127 /* Thread joining APIs. 128 * 129 * These APIs have a strict contract: 130 * - Either PyThread_join_thread or PyThread_detach_thread must be called 131 * exactly once with the given handle. 132 * - Calling neither PyThread_join_thread nor PyThread_detach_thread results 133 * in a resource leak until the end of the process. 134 * - Any other usage, such as calling both PyThread_join_thread and 135 * PyThread_detach_thread, or calling them more than once (including 136 * simultaneously), results in undefined behavior. 137 */ 138 PyAPI_FUNC(int) PyThread_start_joinable_thread(void (*func)(void *), 139 void *arg, 140 PyThread_ident_t* ident, 141 PyThread_handle_t* handle); 142 /* 143 * Join a thread started with `PyThread_start_joinable_thread`. 144 * This function cannot be interrupted. It returns 0 on success, 145 * a non-zero value on failure. 146 */ 147 PyAPI_FUNC(int) PyThread_join_thread(PyThread_handle_t); 148 /* 149 * Detach a thread started with `PyThread_start_joinable_thread`, such 150 * that its resources are relased as soon as it exits. 151 * This function cannot be interrupted. It returns 0 on success, 152 * a non-zero value on failure. 153 */ 154 PyAPI_FUNC(int) PyThread_detach_thread(PyThread_handle_t); 155 156 #ifdef __cplusplus 157 } 158 #endif 159 #endif /* !Py_INTERNAL_PYTHREAD_H */ 160