diff options
author | Pablo Galindo Salgado <Pablogsal@gmail.com> | 2022-10-08 14:57:09 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-08 14:57:09 (GMT) |
commit | 83eb827247dd28b13fd816936c74c162e9f52a2d (patch) | |
tree | 40a8abf0018f178eeadd976ad4cba326f9a86029 /Modules | |
parent | c66dbddfbaa374a6954897809574ee9fb463e393 (diff) | |
download | cpython-83eb827247dd28b13fd816936c74c162e9f52a2d.zip cpython-83eb827247dd28b13fd816936c74c162e9f52a2d.tar.gz cpython-83eb827247dd28b13fd816936c74c162e9f52a2d.tar.bz2 |
gh-97922: Run the GC only on eval breaker (#97920)
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/gcmodule.c | 27 | ||||
-rw-r--r-- | Modules/signalmodule.c | 13 |
2 files changed, 37 insertions, 3 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 97cb6e6..75832e9 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -2253,6 +2253,20 @@ PyObject_IS_GC(PyObject *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) { PyGC_Head *g = AS_GC(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) { diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 0f30b4d..b85d6d1 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -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; } |