From 4ad599501fe8ec58ef2842d26330696820b2cc5c Mon Sep 17 00:00:00 2001 From: RayXu <140802139+F18-Maverick@users.noreply.github.com> Date: Sat, 25 Oct 2025 21:54:52 +0800 Subject: [PATCH 1/5] Docs: Fix a grammatical error in `Doc/c-api/capsule.rst` (GH-140577) "who" -> "which" --- Doc/c-api/capsule.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index 64dc4f5275b512c..6da020efc7f27cd 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -15,7 +15,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. .. c:type:: PyCapsule This subtype of :c:type:`PyObject` represents an opaque value, useful for C - extension modules who need to pass an opaque value (as a :c:expr:`void*` + extension modules which need to pass an opaque value (as a :c:expr:`void*` pointer) through Python code to other C code. It is often used to make a C function pointer defined in one module available to other modules, so the regular import mechanism can be used to access C APIs defined in dynamically From ef4665f9184784ecc7a5084a41d62577a3d338cb Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 19:56:07 +0530 Subject: [PATCH 2/5] gh-140544: store pointer to interpreter state as a thread local for fast access (#140573) --- Include/internal/pycore_freelist.h | 7 ++++--- Include/internal/pycore_pystate.h | 9 +++++++-- .../2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst | 1 + Python/pystate.c | 12 +++++++++--- Tools/c-analyzer/cpython/ignored.tsv | 1 + 5 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-10-25-07-25-52.gh-issue-140544.lwjtQe.rst diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index f3c9a669ad3512a..3a41ec4b54bb069 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 ea3dfbd2eef9c15..503cddc73fc4642 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 000000000000000..51d2b229ee5b80e --- /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 2f76adf50260125..5d0927c6c081965 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 c3b13d69f0de8e0..8b73189fb07dc5e 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 From df07364106abe0923c948fe529525b44248d1f48 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Sat, 25 Oct 2025 20:23:26 +0530 Subject: [PATCH 3/5] gh-140544: use faster `_PyInterpreterState_GET` for type lock (#140584) --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6cc6d366a3598c4..5841deb454da1fd 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -72,7 +72,7 @@ class object "PyObject *" "&PyBaseObject_Type" // the type has been revealed to other threads or we only do those updates // while the stop-the-world mechanism is active. The slots and flags are read // in many places without holding a lock and without atomics. -#define TYPE_LOCK &PyInterpreterState_Get()->types.mutex +#define TYPE_LOCK &_PyInterpreterState_GET()->types.mutex #define BEGIN_TYPE_LOCK() Py_BEGIN_CRITICAL_SECTION_MUTEX(TYPE_LOCK) #define END_TYPE_LOCK() Py_END_CRITICAL_SECTION() From 2a1c9bd616b1b3a07c74d280e3f7e2bd94d0cc22 Mon Sep 17 00:00:00 2001 From: Shamil Date: Sat, 25 Oct 2025 17:59:12 +0300 Subject: [PATCH 4/5] Remove unreachable break statements in _ctypes_test.c (#140585) --- Modules/_ctypes/_ctypes_test.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c index 66338805007853b..a0c9d8b70fee469 100644 --- a/Modules/_ctypes/_ctypes_test.c +++ b/Modules/_ctypes/_ctypes_test.c @@ -989,13 +989,10 @@ EXPORT(RECT) ReturnRect(int i, RECT ar, RECT* br, POINT cp, RECT dr, { case 0: return ar; - break; case 1: return dr; - break; case 2: return gr; - break; } return ar; From d74a96366df58b6e55d4a03612c3e67da2211ddd Mon Sep 17 00:00:00 2001 From: RayXu <140802139+F18-Maverick@users.noreply.github.com> Date: Sat, 25 Oct 2025 23:34:45 +0800 Subject: [PATCH 5/5] Fix typo in `Doc/c-api/code.rst` (#140586) --- Doc/c-api/code.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst index 717b0da8f87c7f7..c9741b61254b190 100644 --- a/Doc/c-api/code.rst +++ b/Doc/c-api/code.rst @@ -289,7 +289,7 @@ may change without deprecation warnings. .. c:function:: Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free) - Return a new an opaque index value used to adding data to code objects. + Return a new opaque index value used to adding data to code objects. You generally call this function once (per interpreter) and use the result with ``PyCode_GetExtra`` and ``PyCode_SetExtra`` to manipulate