Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:50

0001 #ifndef Py_INTERNAL_PYTHREAD_H
0002 #define Py_INTERNAL_PYTHREAD_H
0003 #ifdef __cplusplus
0004 extern "C" {
0005 #endif
0006 
0007 #ifndef Py_BUILD_CORE
0008 #  error "this header requires Py_BUILD_CORE define"
0009 #endif
0010 
0011 #include "dynamic_annotations.h" // _Py_ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
0012 #include "pycore_llist.h"        // struct llist_node
0013 
0014 // Get _POSIX_THREADS and _POSIX_SEMAPHORES macros if available
0015 #if (defined(HAVE_UNISTD_H) && !defined(_POSIX_THREADS) \
0016                             && !defined(_POSIX_SEMAPHORES))
0017 #  include <unistd.h>             // _POSIX_THREADS, _POSIX_SEMAPHORES
0018 #endif
0019 #if (defined(HAVE_PTHREAD_H) && !defined(_POSIX_THREADS) \
0020                              && !defined(_POSIX_SEMAPHORES))
0021    // This means pthreads are not implemented in libc headers, hence the macro
0022    // not present in <unistd.h>. But they still can be implemented as an
0023    // external library (e.g. gnu pth in pthread emulation)
0024 #  include <pthread.h>            // _POSIX_THREADS, _POSIX_SEMAPHORES
0025 #endif
0026 #if !defined(_POSIX_THREADS) && defined(__hpux) && defined(_SC_THREADS)
0027    // Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
0028    // enough of the POSIX threads package is implemented to support Python
0029    // threads.
0030    //
0031    // This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
0032    // a check of __ia64 to verify that we're running on an ia64 system instead
0033    // of a pa-risc system.
0034 #  define _POSIX_THREADS
0035 #endif
0036 
0037 
0038 #if defined(_POSIX_THREADS) || defined(HAVE_PTHREAD_STUBS)
0039 #  define _USE_PTHREADS
0040 #endif
0041 
0042 #if defined(_USE_PTHREADS) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
0043 // monotonic is supported statically.  It doesn't mean it works on runtime.
0044 #  define CONDATTR_MONOTONIC
0045 #endif
0046 
0047 
0048 #if defined(HAVE_PTHREAD_STUBS)
0049 #include "cpython/pthread_stubs.h"  // PTHREAD_KEYS_MAX
0050 #include <stdbool.h>                // bool
0051 
0052 // pthread_key
0053 struct py_stub_tls_entry {
0054     bool in_use;
0055     void *value;
0056 };
0057 #endif
0058 
0059 struct _pythread_runtime_state {
0060     int initialized;
0061 
0062 #ifdef _USE_PTHREADS
0063     // This matches when thread_pthread.h is used.
0064     struct {
0065         /* NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported. */
0066         pthread_condattr_t *ptr;
0067 # ifdef CONDATTR_MONOTONIC
0068     /* The value to which condattr_monotonic is set. */
0069         pthread_condattr_t val;
0070 # endif
0071     } _condattr_monotonic;
0072 
0073 #endif  // USE_PTHREADS
0074 
0075 #if defined(HAVE_PTHREAD_STUBS)
0076     struct {
0077         struct py_stub_tls_entry tls_entries[PTHREAD_KEYS_MAX];
0078     } stubs;
0079 #endif
0080 
0081     // Linked list of ThreadHandles
0082     struct llist_node handles;
0083 };
0084 
0085 #define _pythread_RUNTIME_INIT(pythread) \
0086     { \
0087         .handles = LLIST_INIT(pythread.handles), \
0088     }
0089 
0090 #ifdef HAVE_FORK
0091 /* Private function to reinitialize a lock at fork in the child process.
0092    Reset the lock to the unlocked state.
0093    Return 0 on success, return -1 on error. */
0094 extern int _PyThread_at_fork_reinit(PyThread_type_lock *lock);
0095 extern void _PyThread_AfterFork(struct _pythread_runtime_state *state);
0096 #endif  /* HAVE_FORK */
0097 
0098 
0099 // unset: -1 seconds, in nanoseconds
0100 #define PyThread_UNSET_TIMEOUT ((PyTime_t)(-1 * 1000 * 1000 * 1000))
0101 
0102 // Exported for the _interpchannels module.
0103 PyAPI_FUNC(int) PyThread_ParseTimeoutArg(
0104     PyObject *arg,
0105     int blocking,
0106     PY_TIMEOUT_T *timeout);
0107 
0108 /* Helper to acquire an interruptible lock with a timeout.  If the lock acquire
0109  * is interrupted, signal handlers are run, and if they raise an exception,
0110  * PY_LOCK_INTR is returned.  Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
0111  * are returned, depending on whether the lock can be acquired within the
0112  * timeout.
0113  */
0114 // Exported for the _interpchannels module.
0115 PyAPI_FUNC(PyLockStatus) PyThread_acquire_lock_timed_with_retries(
0116     PyThread_type_lock,
0117     PY_TIMEOUT_T microseconds);
0118 
0119 typedef unsigned long long PyThread_ident_t;
0120 typedef Py_uintptr_t PyThread_handle_t;
0121 
0122 #define PY_FORMAT_THREAD_IDENT_T "llu"
0123 #define Py_PARSE_THREAD_IDENT_T "K"
0124 
0125 PyAPI_FUNC(PyThread_ident_t) PyThread_get_thread_ident_ex(void);
0126 
0127 /* Thread joining APIs.
0128  *
0129  * These APIs have a strict contract:
0130  *  - Either PyThread_join_thread or PyThread_detach_thread must be called
0131  *    exactly once with the given handle.
0132  *  - Calling neither PyThread_join_thread nor PyThread_detach_thread results
0133  *    in a resource leak until the end of the process.
0134  *  - Any other usage, such as calling both PyThread_join_thread and
0135  *    PyThread_detach_thread, or calling them more than once (including
0136  *    simultaneously), results in undefined behavior.
0137  */
0138 PyAPI_FUNC(int) PyThread_start_joinable_thread(void (*func)(void *),
0139                                                void *arg,
0140                                                PyThread_ident_t* ident,
0141                                                PyThread_handle_t* handle);
0142 /*
0143  * Join a thread started with `PyThread_start_joinable_thread`.
0144  * This function cannot be interrupted. It returns 0 on success,
0145  * a non-zero value on failure.
0146  */
0147 PyAPI_FUNC(int) PyThread_join_thread(PyThread_handle_t);
0148 /*
0149  * Detach a thread started with `PyThread_start_joinable_thread`, such
0150  * that its resources are relased as soon as it exits.
0151  * This function cannot be interrupted. It returns 0 on success,
0152  * a non-zero value on failure.
0153  */
0154 PyAPI_FUNC(int) PyThread_detach_thread(PyThread_handle_t);
0155 
0156 #ifdef __cplusplus
0157 }
0158 #endif
0159 #endif /* !Py_INTERNAL_PYTHREAD_H */