gh-97922: Run the GC only on eval breaker (#97920)

This commit is contained in:
Pablo Galindo Salgado 2022-10-08 07:57:09 -07:00 committed by GitHub
parent c66dbddfba
commit 83eb827247
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 14 deletions

View file

@ -2252,6 +2252,20 @@ PyObject_IS_GC(PyObject *obj)
return _PyObject_IS_GC(obj);
}
void
_Py_ScheduleGC(PyInterpreterState *interp)
{
GCState *gcstate = &interp->gc;
if (gcstate->collecting == 1) {
return;
}
struct _ceval_state *ceval = &interp->ceval;
if (!_Py_atomic_load_relaxed(&ceval->gc_scheduled)) {
_Py_atomic_store_relaxed(&ceval->gc_scheduled, 1);
_Py_atomic_store_relaxed(&ceval->eval_breaker, 1);
}
}
void
_PyObject_GC_Link(PyObject *op)
{
@ -2269,12 +2283,19 @@ _PyObject_GC_Link(PyObject *op)
!gcstate->collecting &&
!_PyErr_Occurred(tstate))
{
gcstate->collecting = 1;
gc_collect_generations(tstate);
gcstate->collecting = 0;
_Py_ScheduleGC(tstate->interp);
}
}
void
_Py_RunGC(PyThreadState *tstate)
{
GCState *gcstate = &tstate->interp->gc;
gcstate->collecting = 1;
gc_collect_generations(tstate);
gcstate->collecting = 0;
}
static PyObject *
gc_alloc(size_t basicsize, size_t presize)
{

View file

@ -1798,6 +1798,19 @@ int
PyErr_CheckSignals(void)
{
PyThreadState *tstate = _PyThreadState_GET();
/* Opportunistically check if the GC is scheduled to run and run it
if we have a request. This is done here because native code needs
to call this API if is going to run for some time without executing
Python code to ensure signals are handled. Checking for the GC here
allows long running native code to clean cycles created using the C-API
even if it doesn't run the evaluation loop */
struct _ceval_state *interp_ceval_state = &tstate->interp->ceval;
if (_Py_atomic_load_relaxed(&interp_ceval_state->gc_scheduled)) {
_Py_atomic_store_relaxed(&interp_ceval_state->gc_scheduled, 0);
_Py_RunGC(tstate);
}
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
return 0;
}