diff --git a/Misc/NEWS.d/next/Core and Builtins/2025-12-01-20-41-26.gh-issue-142048.c2YosX.rst b/Misc/NEWS.d/next/Core and Builtins/2025-12-01-20-41-26.gh-issue-142048.c2YosX.rst new file mode 100644 index 00000000000000..1400dae13ffe32 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2025-12-01-20-41-26.gh-issue-142048.c2YosX.rst @@ -0,0 +1,2 @@ +Fix quadratically increasing garbage collection delays in free-threaded +build. diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index 6a38cc224a4bf8..7c7e7b21e55a7d 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -1100,7 +1100,19 @@ record_deallocation(PyThreadState *tstate) gc->alloc_count--; if (gc->alloc_count <= -LOCAL_ALLOC_COUNT_THRESHOLD) { GCState *gcstate = &tstate->interp->gc; - _Py_atomic_add_int(&gcstate->generations[0].count, (int)gc->alloc_count); + int count = _Py_atomic_load_int_relaxed(&gcstate->generations[0].count); + int new_count; + do { + if (count == 0) { + break; + } + new_count = count + (int)gc->alloc_count; + if (new_count < 0) { + new_count = 0; + } + } while (!_Py_atomic_compare_exchange_int(&gcstate->generations[0].count, + &count, + new_count)); gc->alloc_count = 0; } }