gh-112175: Add eval_breaker to PyThreadState (#115194)

This change adds an `eval_breaker` field to `PyThreadState`. The primary
motivation is for performance in free-threaded builds: with thread-local eval
breakers, we can stop a specific thread (e.g., for an async exception) without
interrupting other threads.

The source of truth for the global instrumentation version is stored in the
`instrumentation_version` field in PyInterpreterState. Threads usually read the
version from their local `eval_breaker`, where it continues to be colocated
with the eval breaker bits.
This commit is contained in:
Brett Simmers 2024-02-20 06:57:48 -08:00 committed by GitHub
parent e71468ba4f
commit 0749244d13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 265 additions and 172 deletions

View file

@ -1771,9 +1771,12 @@ PyObject_IS_GC(PyObject *obj)
}
void
_Py_ScheduleGC(PyInterpreterState *interp)
_Py_ScheduleGC(PyThreadState *tstate)
{
_Py_set_eval_breaker_bit(interp, _PY_GC_SCHEDULED_BIT, 1);
if (!_Py_eval_breaker_bit_is_set(tstate, _PY_GC_SCHEDULED_BIT))
{
_Py_set_eval_breaker_bit(tstate, _PY_GC_SCHEDULED_BIT);
}
}
void
@ -1794,7 +1797,7 @@ _PyObject_GC_Link(PyObject *op)
!_Py_atomic_load_int_relaxed(&gcstate->collecting) &&
!_PyErr_Occurred(tstate))
{
_Py_ScheduleGC(tstate->interp);
_Py_ScheduleGC(tstate);
}
}