https://github.com/python/cpython/commit/ef4665f9184784ecc7a5084a41d62577a3d338cb
commit: ef4665f9184784ecc7a5084a41d62577a3d338cb
branch: main
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-10-25T19:56:07+05:30
summary:
gh-140544: store pointer to interpreter state as a thread local for fast access
(#140573)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst
M Include/internal/pycore_freelist.h
M Include/internal/pycore_pystate.h
M Python/pystate.c
M Tools/c-analyzer/cpython/ignored.tsv
diff --git a/Include/internal/pycore_freelist.h
b/Include/internal/pycore_freelist.h
index f3c9a669ad3512..3a41ec4b54bb06 100644
--- a/Include/internal/pycore_freelist.h
+++ b/Include/internal/pycore_freelist.h
@@ -17,15 +17,16 @@ extern "C" {
static inline struct _Py_freelists *
_Py_freelists_GET(void)
{
- PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
- _Py_EnsureTstateNotNULL(tstate);
+ _Py_AssertHoldsTstate();
#endif
#ifdef Py_GIL_DISABLED
+ PyThreadState *tstate = _PyThreadState_GET();
return &((_PyThreadStateImpl*)tstate)->freelists;
#else
- return &tstate->interp->object_state.freelists;
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ return &interp->object_state.freelists;
#endif
}
diff --git a/Include/internal/pycore_pystate.h
b/Include/internal/pycore_pystate.h
index ea3dfbd2eef9c1..503cddc73fc464 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -91,6 +91,7 @@ _Py_ThreadCanHandleSignals(PyInterpreterState *interp)
#if defined(HAVE_THREAD_LOCAL) && !defined(Py_BUILD_CORE_MODULE)
extern _Py_thread_local PyThreadState *_Py_tss_tstate;
+extern _Py_thread_local PyInterpreterState *_Py_tss_interp;
#endif
#ifndef NDEBUG
@@ -204,11 +205,15 @@ _Py_EnsureFuncTstateNotNULL(const char *func,
PyThreadState *tstate)
See also PyInterpreterState_Get()
and _PyGILState_GetInterpreterStateUnsafe(). */
static inline PyInterpreterState* _PyInterpreterState_GET(void) {
- PyThreadState *tstate = _PyThreadState_GET();
#ifdef Py_DEBUG
+ PyThreadState *tstate = _PyThreadState_GET();
_Py_EnsureTstateNotNULL(tstate);
#endif
- return tstate->interp;
+#if !defined(Py_BUILD_CORE_MODULE)
+ return _Py_tss_interp;
+#else
+ return _PyThreadState_GET()->interp;
+#endif
}
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst
new file mode 100644
index 00000000000000..51d2b229ee5b80
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst
@@ -0,0 +1 @@
+Speed up accessing interpreter state by caching it in a thread local variable.
Patch by Kumar Aditya.
diff --git a/Python/pystate.c b/Python/pystate.c
index 2f76adf5026012..5d0927c6c08196 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -78,6 +78,10 @@ _Py_thread_local PyThreadState *_Py_tss_tstate = NULL;
also known as a "gilstate." */
_Py_thread_local PyThreadState *_Py_tss_gilstate = NULL;
+/* The interpreter of the attached thread state,
+ and is same as tstate->interp. */
+_Py_thread_local PyInterpreterState *_Py_tss_interp = NULL;
+
static inline PyThreadState *
current_fast_get(void)
{
@@ -89,12 +93,15 @@ current_fast_set(_PyRuntimeState *Py_UNUSED(runtime),
PyThreadState *tstate)
{
assert(tstate != NULL);
_Py_tss_tstate = tstate;
+ assert(tstate->interp != NULL);
+ _Py_tss_interp = tstate->interp;
}
static inline void
current_fast_clear(_PyRuntimeState *Py_UNUSED(runtime))
{
_Py_tss_tstate = NULL;
+ _Py_tss_interp = NULL;
}
#define tstate_verify_not_active(tstate) \
@@ -1281,9 +1288,8 @@ _PyInterpreterState_RequireIDRef(PyInterpreterState
*interp, int required)
PyInterpreterState*
PyInterpreterState_Get(void)
{
- PyThreadState *tstate = current_fast_get();
- _Py_EnsureTstateNotNULL(tstate);
- PyInterpreterState *interp = tstate->interp;
+ _Py_AssertHoldsTstate();
+ PyInterpreterState *interp = _Py_tss_interp;
if (interp == NULL) {
Py_FatalError("no current interpreter");
}
diff --git a/Tools/c-analyzer/cpython/ignored.tsv
b/Tools/c-analyzer/cpython/ignored.tsv
index c3b13d69f0de8e..8b73189fb07dc5 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -194,6 +194,7 @@ Python/pyfpe.c - PyFPE_counter -
Python/import.c - pkgcontext -
Python/pystate.c - _Py_tss_tstate -
Python/pystate.c - _Py_tss_gilstate -
+Python/pystate.c - _Py_tss_interp -
##-----------------------
## should be const
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]