summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-02-16 16:22:27 (GMT)
committerGitHub <noreply@github.com>2024-02-16 16:22:27 (GMT)
commitb24c9161a651f549ed48f4b4dba8996fe9cc4e09 (patch)
tree549acacced5ca0b1923e0df94b40ef633c6cdf8f /Modules
parentf92857a93016aa26ba93959d2bdb690ef52e7f07 (diff)
downloadcpython-b24c9161a651f549ed48f4b4dba8996fe9cc4e09.zip
cpython-b24c9161a651f549ed48f4b4dba8996fe9cc4e09.tar.gz
cpython-b24c9161a651f549ed48f4b4dba8996fe9cc4e09.tar.bz2
gh-112529: Make the GC scheduling thread-safe (#114880)
The GC keeps track of the number of allocations (less deallocations) since the last GC. This buffers the count in thread-local state and uses atomic operations to modify the per-interpreter count. The thread-local buffering avoids contention on shared state. A consequence is that the GC scheduling is not as precise, so "test_sneaky_frame_object" is skipped because it requires that the GC be run exactly after allocating a frame object.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/gcmodule.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c
index a2b66b9..961165e 100644
--- a/Modules/gcmodule.c
+++ b/Modules/gcmodule.c
@@ -201,6 +201,16 @@ gc_get_count_impl(PyObject *module)
/*[clinic end generated code: output=354012e67b16398f input=a392794a08251751]*/
{
GCState *gcstate = get_gc_state();
+
+#ifdef Py_GIL_DISABLED
+ _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
+ struct _gc_thread_state *gc = &tstate->gc;
+
+ // Flush the local allocation count to the global count
+ _Py_atomic_add_int(&gcstate->generations[0].count, (int)gc->alloc_count);
+ gc->alloc_count = 0;
+#endif
+
return Py_BuildValue("(iii)",
gcstate->generations[0].count,
gcstate->generations[1].count,