summaryrefslogtreecommitdiffstats
path: root/Include/internal
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-04-24 17:17:02 (GMT)
committerGitHub <noreply@github.com>2023-04-24 17:17:02 (GMT)
commitf8abfa331421e2c28388c5162f37820495e3c2ee (patch)
tree515ce849a73a0c3f34783e8c1fe22f5593c974da /Include/internal
parent7ef614c1adad2b8857442bf0fea649891b591109 (diff)
downloadcpython-f8abfa331421e2c28388c5162f37820495e3c2ee.zip
cpython-f8abfa331421e2c28388c5162f37820495e3c2ee.tar.gz
cpython-f8abfa331421e2c28388c5162f37820495e3c2ee.tar.bz2
gh-103323: Get the "Current" Thread State from a Thread-Local Variable (gh-103324)
We replace _PyRuntime.tstate_current with a thread-local variable. As part of this change, we add a _Py_thread_local macro in pyport.h (only for the core runtime) to smooth out the compiler differences. The main motivation here is in support of a per-interpreter GIL, but this change also provides some performance improvement opportunities. Note that we do not provide a fallback to the thread-local, either falling back to the old tstate_current or to thread-specific storage (PyThread_tss_*()). If that proves problematic then we can circle back. I consider it unlikely, but will run the buildbots to double-check. Also note that this does not change any of the code related to the GILState API, where it uses a thread state stored in thread-specific storage. I suspect we can combine that with _Py_tss_tstate (from here). However, that can be addressed separately and is not urgent (nor critical). (While this change was mostly done independently, I did take some inspiration from earlier (~2020) work by @markshannon (main...markshannon:threadstate_in_tls) and @vstinner (#23976).)
Diffstat (limited to 'Include/internal')
-rw-r--r--Include/internal/pycore_pystate.h26
-rw-r--r--Include/internal/pycore_runtime.h3
2 files changed, 17 insertions, 12 deletions
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index 6e5f228..c40f9e7 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -64,17 +64,14 @@ _Py_ThreadCanHandlePendingCalls(void)
/* Variable and macro for in-line access to current thread
and interpreter state */
-static inline PyThreadState*
-_PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
-{
- return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->tstate_current);
-}
+#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
+extern _Py_thread_local PyThreadState *_Py_tss_tstate;
+#endif
+PyAPI_DATA(PyThreadState *) _PyThreadState_GetCurrent(void);
/* Get the current Python thread state.
- Efficient macro reading directly the 'tstate_current' atomic
- variable. The macro is unsafe: it does not check for error and it can
- return NULL.
+ This function is unsafe: it does not check for error and it can return NULL.
The caller must hold the GIL.
@@ -82,9 +79,20 @@ _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime)
static inline PyThreadState*
_PyThreadState_GET(void)
{
- return _PyRuntimeState_GetThreadState(&_PyRuntime);
+#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
+ return _Py_tss_tstate;
+#else
+ return _PyThreadState_GetCurrent();
+#endif
+}
+
+static inline PyThreadState*
+_PyRuntimeState_GetThreadState(_PyRuntimeState *Py_UNUSED(runtime))
+{
+ return _PyThreadState_GET();
}
+
static inline void
_Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
{
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 3ebe499..2a3fd8a 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -119,9 +119,6 @@ typedef struct pyruntimestate {
unsigned long main_thread;
- /* Assuming the current thread holds the GIL, this is the
- PyThreadState for the current thread. */
- _Py_atomic_address tstate_current;
/* Used for the thread state bound to the current thread. */
Py_tss_t autoTSSkey;