From f7af8bc58aaa0c76028ddee54e635daedcd1b40c Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Fri, 7 Feb 2025 08:11:17 +0900 Subject: [PATCH] =?UTF-8?q?=20[3.13]=20gh-129533:=20Update=20PyGC=5FEnable?= =?UTF-8?q?/Disable/IsEnabled=20to=20use=20atomic=20operat=E2=80=A6=20(gh-?= =?UTF-8?q?129756)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh-129533: Update PyGC_Enable/Disable/IsEnabled to use atomic operation (gh-129563) (cherry picked from commit b184abf074c0e1f379a238f07da5616460f36b93) --- ...5-02-02-12-58-21.gh-issue-129533.dFfqkT.rst | 3 +++ Python/gc_free_threading.c | 18 +++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst diff --git a/Misc/NEWS.d/next/C API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst b/Misc/NEWS.d/next/C API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst new file mode 100644 index 000000000000..20e93e2bcc1f --- /dev/null +++ b/Misc/NEWS.d/next/C API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst @@ -0,0 +1,3 @@ +Update :c:func:`PyGC_Enable()`, :c:func:`PyGC_Disable()`, +:c:func:`PyGC_IsEnabled()` to use atomic operation for thread-safety +at free-threading build. Patch by Donghee Na. diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c index ff86c759eb2c..6a38cc224a4b 100644 --- a/Python/gc_free_threading.c +++ b/Python/gc_free_threading.c @@ -1059,7 +1059,8 @@ gc_should_collect(GCState *gcstate) { int count = _Py_atomic_load_int_relaxed(&gcstate->generations[0].count); int threshold = gcstate->generations[0].threshold; - if (count <= threshold || threshold == 0 || !gcstate->enabled) { + int gc_enabled = _Py_atomic_load_int_relaxed(&gcstate->enabled); + if (count <= threshold || threshold == 0 || !gc_enabled) { return false; } // Avoid quadratic behavior by scaling threshold to the number of live @@ -1495,25 +1496,21 @@ int PyGC_Enable(void) { GCState *gcstate = get_gc_state(); - int old_state = gcstate->enabled; - gcstate->enabled = 1; - return old_state; + return _Py_atomic_exchange_int(&gcstate->enabled, 1); } int PyGC_Disable(void) { GCState *gcstate = get_gc_state(); - int old_state = gcstate->enabled; - gcstate->enabled = 0; - return old_state; + return _Py_atomic_exchange_int(&gcstate->enabled, 0); } int PyGC_IsEnabled(void) { GCState *gcstate = get_gc_state(); - return gcstate->enabled; + return _Py_atomic_load_int_relaxed(&gcstate->enabled); } /* Public API to invoke gc.collect() from C */ @@ -1523,7 +1520,7 @@ PyGC_Collect(void) PyThreadState *tstate = _PyThreadState_GET(); GCState *gcstate = &tstate->interp->gc; - if (!gcstate->enabled) { + if (!_Py_atomic_load_int_relaxed(&gcstate->enabled)) { return 0; } @@ -1681,8 +1678,7 @@ _PyObject_GC_Link(PyObject *op) void _Py_RunGC(PyThreadState *tstate) { - GCState *gcstate = get_gc_state(); - if (!gcstate->enabled) { + if (!PyGC_IsEnabled()) { return; } gc_collect_main(tstate, 0, _Py_GC_REASON_HEAP);