Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/c-api/capsule.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Doc/c-api/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions Include/internal/pycore_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
9 changes: 7 additions & 2 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Speed up accessing interpreter state by caching it in a thread local variable. Patch by Kumar Aditya.
3 changes: 0 additions & 3 deletions Modules/_ctypes/_ctypes_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
12 changes: 9 additions & 3 deletions Python/pystate.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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) \
Expand Down Expand Up @@ -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");
}
Expand Down
1 change: 1 addition & 0 deletions Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading