# Bug report ### Bug description: `gc_set_threshold_impl` writes `gcstate->young.threshold` https://github.com/python/cpython/blob/69e0a78e6edc3166c7a5b166955c0cefd1bacd5d/Modules/gcmodule.c#L154-L161 while `gc_should_collect()` reads `gcstate->young.threshold` non atomically https://github.com/python/cpython/blob/69e0a78e6edc3166c7a5b166955c0cefd1bacd5d/Python/gc_free_threading.c#L2198-L2203 Reproducer: ```python import sys import gc from threading import Thread, Barrier class C: pass N_THREADS = 8 N_ITERS = 100_000 barrier = Barrier(N_THREADS) def allocator(): barrier.wait() keep = [] for i in range(N_ITERS): a = C(); b = C() a.r = b; b.r = a if i % 100 == 0: keep.append(a) if len(keep) > 1000: keep.clear() def setter(): barrier.wait() for i in range(N_ITERS): gc.set_threshold(100 + (i & 0x3F), 10, 10) threads = [Thread(target=allocator) for _ in range(N_THREADS - 1)] threads.append(Thread(target=setter)) for t in threads: t.start() for t in threads: t.join() ``` TSAN Report: ``` WARNING: ThreadSanitizer: data race (pid=482463) Read of size 4 at 0x555555e38f80 by thread T5: #0 gc_should_collect_mem_usage /cpython/Python/gc_free_threading.c:2168:36 (python3.15t+0x4a90c3) #1 gc_should_collect /cpython/Python/gc_free_threading.c:2217:12 (python3.15t+0x4a90c3) #2 record_allocation /cpython/Python/gc_free_threading.c:2234:13 (python3.15t+0x4a8324) #3 _PyObject_GC_Link /cpython/Python/gc_free_threading.c:2914:5 (python3.15t+0x4a8324) #4 _PyType_AllocNoTrack /cpython/Objects/typeobject.c:2537:9 (python3.15t+0x322b3d) #5 PyType_GenericAlloc /cpython/Objects/typeobject.c:2558:21 (python3.15t+0x32291e) #6 object_new /cpython/Objects/typeobject.c:7340:21 (python3.15t+0x32ed3b) #7 type_call /cpython/Objects/typeobject.c:2471:11 (python3.15t+0x32a7e2) #8 _PyObject_MakeTpCall /cpython/Objects/call.c:242:18 (python3.15t+0x20ef0f) #9 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:142:16 (python3.15t+0x20fcf7) #10 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fcf7) #11 _Py_VectorCall_StackRefSteal /cpython/Python/ceval.c:733:11 (python3.15t+0x428ab9) #12 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4344:35 (python3.15t+0x435c37) #13 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) #14 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660) #15 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) #16 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) #17 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9) #18 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) #19 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x480a91) #20 context_run /cpython/Python/context.c:727:29 (python3.15t+0x480a91) #21 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x229fe7) #22 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x20fc33) #23 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fc33) #24 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42928c) #25 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1841:35 (python3.15t+0x42f07c) #26 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) #27 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660) #28 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) #29 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) #30 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9) #31 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) #32 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x20ff3b) #33 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x20ff3b) #34 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x20ffa5) #35 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x605bc2) #36 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x535427) Previous write of size 4 at 0x555555e38f80 by thread T8: #0 gc_set_threshold_impl /cpython/Modules/gcmodule.c:161:30 (python3.15t+0x5510f6) #1 gc_set_threshold /cpython/Modules/clinic/gcmodule.c.h:266:20 (python3.15t+0x5510f6) #2 cfunction_call /cpython/Objects/methodobject.c:575:18 (python3.15t+0x2c10d1) #3 _PyObject_MakeTpCall /cpython/Objects/call.c:242:18 (python3.15t+0x20ef0f) #4 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:142:16 (python3.15t+0x20fcf7) #5 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fcf7) #6 _Py_VectorCall_StackRefSteal /cpython/Python/ceval.c:733:11 (python3.15t+0x428ab9) #7 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:4344:35 (python3.15t+0x435c37) #8 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) #9 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660) #10 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) #11 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) #12 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9) #13 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) #14 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x480a91) #15 context_run /cpython/Python/context.c:727:29 (python3.15t+0x480a91) #16 method_vectorcall_FASTCALL_KEYWORDS /cpython/Objects/descrobject.c:421:24 (python3.15t+0x229fe7) #17 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x20fc33) #18 PyObject_Vectorcall /cpython/Objects/call.c:327:12 (python3.15t+0x20fc33) #19 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:775:11 (python3.15t+0x42928c) #20 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1841:35 (python3.15t+0x42f07c) #21 _PyEval_EvalFrame /cpython/./Include/internal/pycore_ceval.h:118:16 (python3.15t+0x428660) #22 _PyEval_Vector /cpython/Python/ceval.c:2124:12 (python3.15t+0x428660) #23 _PyFunction_Vectorcall /cpython/Objects/call.c (python3.15t+0x2102af) #24 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11 (python3.15t+0x211de9) #25 _PyObject_VectorcallPrepend /cpython/Objects/call.c:855:20 (python3.15t+0x211de9) #26 method_vectorcall /cpython/Objects/classobject.c:55:12 (python3.15t+0x21531f) #27 _PyVectorcall_Call /cpython/Objects/call.c:273:16 (python3.15t+0x20ff3b) #28 _PyObject_Call /cpython/Objects/call.c:348:16 (python3.15t+0x20ff3b) #29 PyObject_Call /cpython/Objects/call.c:373:12 (python3.15t+0x20ffa5) #30 thread_run /cpython/./Modules/_threadmodule.c:388:21 (python3.15t+0x605bc2) #31 pythread_wrapper /cpython/Python/thread_pthread.h:234:5 (python3.15t+0x535427) Location is global '_PyRuntime' of size 405120 at 0x555555e108c0 (python3.15t+0x8e4f80) ``` ### CPython versions tested on: Python 3.15.0a8+ free-threading build (heads/main:44f1b987ed1, Apr 14 2026, 07:56:49) ### Operating systems tested on: Ubuntu <!-- gh-linked-prs --> ### Linked PRs * gh-150356 * gh-150841 * gh-150842 <!-- /gh-linked-prs -->