]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-129533: Update PyGC_Enable/Disable/IsEnabled to use atomic operat… (gh...
authorDonghee Na <donghee.na@python.org>
Thu, 6 Feb 2025 23:11:17 +0000 (08:11 +0900)
committerGitHub <noreply@github.com>
Thu, 6 Feb 2025 23:11:17 +0000 (23:11 +0000)
gh-129533: Update PyGC_Enable/Disable/IsEnabled to use atomic operation  (gh-129563)

(cherry picked from commit b184abf074c0e1f379a238f07da5616460f36b93)

Misc/NEWS.d/next/C API/2025-02-02-12-58-21.gh-issue-129533.dFfqkT.rst [new file with mode: 0644]
Python/gc_free_threading.c

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 (file)
index 0000000..20e93e2
--- /dev/null
@@ -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.
index ff86c759eb2c1c9bc12b04f290fb20c1bde328be..6a38cc224a4bf88349e98dd5871983943ed5dec5 100644 (file)
@@ -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);