[Python-checkins] gh-81057: Move Threading-Related Globals to _PyRuntimeState (#100084)

ericsnowcurrently webhook-mailer at python.org
Thu Dec 8 19:51:03 EST 2022


https://github.com/python/cpython/commit/1160001b34615066b1188d5fb457131b1ebb928d
commit: 1160001b34615066b1188d5fb457131b1ebb928d
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2022-12-08T17:50:58-07:00
summary:

gh-81057: Move Threading-Related Globals to _PyRuntimeState (#100084)

https://github.com/python/cpython/issues/81057

files:
A Include/internal/pycore_pythread.h
M Include/internal/pycore_runtime.h
M Makefile.pre.in
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Python/thread.c
M Python/thread_nt.h
M Python/thread_pthread.h
M Python/thread_pthread_stubs.h
M Tools/c-analyzer/cpython/globals-to-fix.tsv
M Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/internal/pycore_pythread.h b/Include/internal/pycore_pythread.h
new file mode 100644
index 000000000000..4aeb285b89a8
--- /dev/null
+++ b/Include/internal/pycore_pythread.h
@@ -0,0 +1,81 @@
+#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 */
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index ac89c7d378e2..fe2de5feb47a 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -20,6 +20,7 @@ extern "C" {
 #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
@@ -96,6 +97,7 @@ typedef struct pyruntimestate {
         int unhandled_keyboard_interrupt;
     } signals;
     struct _time_runtime_state time;
+    struct _pythread_runtime_state threads;
 
     struct pyinterpreters {
         PyThread_type_lock mutex;
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 312031999df0..de42d684f166 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1663,6 +1663,7 @@ PYTHON_HEADERS= \
 		$(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 \
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 58ea6ae7b4aa..35fbff320f46 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -245,6 +245,7 @@
     <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" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 96c3bd6c30e9..19cb5cf1c807 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -639,6 +639,9 @@
     <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>
diff --git a/Python/thread.c b/Python/thread.c
index 3c1e78ed1bca..4581f1af043a 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -8,15 +8,7 @@
 #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>
@@ -24,33 +16,17 @@
 
 #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();
 }
@@ -58,7 +34,7 @@ PyThread_init_thread(void)
 #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
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index d1f1323948a6..26f441bd6d3c 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -152,11 +152,12 @@ unsigned long PyThread_get_thread_native_id(void);
 #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.
 }
 
 /*
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 1c5b320813af..ae312e987bd6 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -119,20 +119,16 @@
  * 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
     }
@@ -192,15 +188,21 @@ typedef struct {
     "%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();
 }
 
diff --git a/Python/thread_pthread_stubs.h b/Python/thread_pthread_stubs.h
index 8b80c0f87e25..56e5b6141924 100644
--- a/Python/thread_pthread_stubs.h
+++ b/Python/thread_pthread_stubs.h
@@ -124,13 +124,10 @@ pthread_attr_destroy(pthread_attr_t *attr)
     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 *))
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index f774cdeab386..94e9831db1fd 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -306,7 +306,6 @@ Objects/sliceobject.c	-	_Py_EllipsisObject	-
 ## state
 
 Objects/object.c	-	_Py_RefTotal	-
-Python/thread_pthread_stubs.h	-	py_tls_entries	-
 
 
 ##################################
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 814c55b75c09..7d6ff0ba6d64 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -22,11 +22,8 @@ Python/fileutils.c	set_inheritable	ioctl_works	-
 # 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)



More information about the Python-checkins mailing list