--- /dev/null
+#ifndef Py_INTERNAL_PYTHREAD_H
+#define Py_INTERNAL_PYTHREAD_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+# error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+#ifndef _POSIX_THREADS
+/* This means pthreads are not implemented in libc headers, hence the macro
+ not present in unistd.h. But they still can be implemented as an external
+ library (e.g. gnu pth in pthread emulation) */
+# ifdef HAVE_PTHREAD_H
+# include <pthread.h> /* _POSIX_THREADS */
+# endif
+# ifndef _POSIX_THREADS
+/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
+ enough of the Posix threads package is implemented to support python
+ threads.
+
+ This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
+ a check of __ia64 to verify that we're running on an ia64 system instead
+ of a pa-risc system.
+*/
+# ifdef __hpux
+# ifdef _SC_THREADS
+# define _POSIX_THREADS
+# endif
+# endif
+# endif /* _POSIX_THREADS */
+#endif /* _POSIX_THREADS */
+
+#if defined(_POSIX_THREADS) && !defined(HAVE_PTHREAD_STUBS)
+# define _USE_PTHREADS
+#endif
+
+#if defined(_USE_PTHREADS) && defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
+// monotonic is supported statically. It doesn't mean it works on runtime.
+# define CONDATTR_MONOTONIC
+#endif
+
+
+#if defined(HAVE_PTHREAD_STUBS)
+// pthread_key
+struct py_stub_tls_entry {
+ bool in_use;
+ void *value;
+};
+#endif
+
+struct _pythread_runtime_state {
+ int initialized;
+
+#ifdef _USE_PTHREADS
+ // This matches when thread_pthread.h is used.
+ struct {
+ /* NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported. */
+ pthread_condattr_t *ptr;
+# ifdef CONDATTR_MONOTONIC
+ /* The value to which condattr_monotonic is set. */
+ pthread_condattr_t val;
+# endif
+ } _condattr_monotonic;
+
+#endif // USE_PTHREADS
+
+#if defined(HAVE_PTHREAD_STUBS)
+ struct {
+ struct py_stub_tls_entry tls_entries[PTHREAD_KEYS_MAX];
+ } stubs;
+#endif
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_PYTHREAD_H */
#include "pycore_parser.h" // struct _parser_runtime_state
#include "pycore_pymem.h" // struct _pymem_allocators
#include "pycore_pyhash.h" // struct pyhash_runtime_state
+#include "pycore_pythread.h" // struct _pythread_runtime_state
#include "pycore_obmalloc.h" // struct obmalloc_state
#include "pycore_time.h" // struct _time_runtime_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
int unhandled_keyboard_interrupt;
} signals;
struct _time_runtime_state time;
+ struct _pythread_runtime_state threads;
struct pyinterpreters {
PyThread_type_lock mutex;
$(srcdir)/Include/internal/pycore_pymem.h \
$(srcdir)/Include/internal/pycore_pymem_init.h \
$(srcdir)/Include/internal/pycore_pystate.h \
+ $(srcdir)/Include/internal/pycore_pythread.h \
$(srcdir)/Include/internal/pycore_range.h \
$(srcdir)/Include/internal/pycore_runtime.h \
$(srcdir)/Include/internal/pycore_runtime_init_generated.h \
<ClInclude Include="..\Include\internal\pycore_pymem.h" />
<ClInclude Include="..\Include\internal\pycore_pymem_init.h" />
<ClInclude Include="..\Include\internal\pycore_pystate.h" />
+ <ClInclude Include="..\Include\internal\pycore_pythread.h" />
<ClInclude Include="..\Include\internal\pycore_range.h" />
<ClInclude Include="..\Include\internal\pycore_runtime.h" />
<ClInclude Include="..\Include\internal\pycore_runtime_init.h" />
<ClInclude Include="..\Include\internal\pycore_pystate.h">
<Filter>Include\internal</Filter>
</ClInclude>
+ <ClInclude Include="..\Include\internal\pycore_pythread.h">
+ <Filter>Include\internal</Filter>
+ </ClInclude>
<ClInclude Include="..\Include\internal\pycore_range.h">
<Filter>Include\internal</Filter>
</ClInclude>
#include "Python.h"
#include "pycore_pystate.h" // _PyInterpreterState_GET()
#include "pycore_structseq.h" // _PyStructSequence_FiniType()
-
-#ifndef _POSIX_THREADS
-/* This means pthreads are not implemented in libc headers, hence the macro
- not present in unistd.h. But they still can be implemented as an external
- library (e.g. gnu pth in pthread emulation) */
-# ifdef HAVE_PTHREAD_H
-# include <pthread.h> /* _POSIX_THREADS */
-# endif
-#endif
+#include "pycore_pythread.h"
#ifndef DONT_HAVE_STDIO_H
#include <stdio.h>
#include <stdlib.h>
-#ifndef _POSIX_THREADS
-
-/* Check if we're running on HP-UX and _SC_THREADS is defined. If so, then
- enough of the Posix threads package is implemented to support python
- threads.
-
- This is valid for HP-UX 11.23 running on an ia64 system. If needed, add
- a check of __ia64 to verify that we're running on an ia64 system instead
- of a pa-risc system.
-*/
-#ifdef __hpux
-#ifdef _SC_THREADS
-#define _POSIX_THREADS
-#endif
-#endif
-
-#endif /* _POSIX_THREADS */
-
-static int initialized;
static void PyThread__init_thread(void); /* Forward */
+#define initialized _PyRuntime.threads.initialized
+
void
PyThread_init_thread(void)
{
- if (initialized)
+ if (initialized) {
return;
+ }
initialized = 1;
PyThread__init_thread();
}
#if defined(HAVE_PTHREAD_STUBS)
# define PYTHREAD_NAME "pthread-stubs"
# include "thread_pthread_stubs.h"
-#elif defined(_POSIX_THREADS)
+#elif defined(_USE_PTHREADS) /* AKA _PTHREADS */
# if defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__)
# define PYTHREAD_NAME "pthread-stubs"
# else
#endif
/*
- * Initialization of the C package, should not be needed.
+ * Initialization for the current runtime.
*/
static void
PyThread__init_thread(void)
{
+ // Initialization of the C package should not be needed.
}
/*
* pthread_cond support
*/
-#if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
-// monotonic is supported statically. It doesn't mean it works on runtime.
-#define CONDATTR_MONOTONIC
-#endif
-
-// NULL when pthread_condattr_setclock(CLOCK_MONOTONIC) is not supported.
-static pthread_condattr_t *condattr_monotonic = NULL;
+#define condattr_monotonic _PyRuntime.threads._condattr_monotonic.ptr
static void
init_condattr(void)
{
#ifdef CONDATTR_MONOTONIC
- static pthread_condattr_t ca;
+# define ca _PyRuntime.threads._condattr_monotonic.val
+ // XXX We need to check the return code?
pthread_condattr_init(&ca);
+ // XXX We need to run pthread_condattr_destroy() during runtime fini.
if (pthread_condattr_setclock(&ca, CLOCK_MONOTONIC) == 0) {
condattr_monotonic = &ca; // Use monotonic clock
}
"%s: %s\n", name, strerror(status)); error = 1; }
/*
- * Initialization.
+ * Initialization for the current runtime.
*/
static void
PyThread__init_thread(void)
{
+ // The library is only initialized once in the process,
+ // regardless of how many times the Python runtime is initialized.
+ static int lib_initialized = 0;
+ if (!lib_initialized) {
+ lib_initialized = 1;
#if defined(_AIX) && defined(__GNUC__)
- extern void pthread_init(void);
- pthread_init();
+ extern void pthread_init(void);
+ pthread_init();
#endif
+ }
init_condattr();
}
return 0;
}
-// pthread_key
-typedef struct {
- bool in_use;
- void *value;
-} py_tls_entry;
-static py_tls_entry py_tls_entries[PTHREAD_KEYS_MAX] = {0};
+typedef struct py_stub_tls_entry py_tls_entry;
+
+#define py_tls_entries (_PyRuntime.threads.stubs.tls_entries)
int
pthread_key_create(pthread_key_t *key, void (*destr_function)(void *))
## state
Objects/object.c - _Py_RefTotal -
-Python/thread_pthread_stubs.h - py_tls_entries -
##################################
# XXX Is this thread-safe?
Modules/posixmodule.c os_dup2_impl dup3_works -
-## resource init - set during first init
-Python/thread.c - initialized -
-Python/thread_pthread.h - condattr_monotonic -
-# safe static buffer used during one-time initialization
-Python/thread_pthread.h init_condattr ca -
+## guards around resource init
+Python/thread_pthread.h PyThread__init_thread lib_initialized -
##-----------------------
## other values (not Python-specific)