From 727453886652f050b3923edb0916b81598e01718 Mon Sep 17 00:00:00 2001 From: Matt Page Date: Mon, 5 Feb 2024 21:50:45 -0800 Subject: [PATCH] Make `PyInterpreterState.threads.count` thread-safe in free-threaded builds Use atomics --- Include/internal/pycore_interp.h | 2 +- Modules/_threadmodule.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index f7c332ed747cfa..bf8edb522d8f7b 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -112,7 +112,7 @@ struct _is { /* The thread currently executing in the __main__ module, if any. */ PyThreadState *main; /* Used in Modules/_threadmodule.c. */ - long count; + Py_ssize_t count; /* Support for runtime thread stack size tuning. A value of 0 means using the platform's default stack size or the size specified by the THREAD_STACK_SIZE macro. */ diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 5cceb84658deb7..4e37abce23c808 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1225,7 +1225,7 @@ thread_run(void *boot_raw) _PyThreadState_Bind(tstate); PyEval_AcquireThread(tstate); - tstate->interp->threads.count++; + _Py_atomic_add_ssize(&tstate->interp->threads.count, 1); PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs); if (res == NULL) { @@ -1243,7 +1243,7 @@ thread_run(void *boot_raw) thread_bootstate_free(boot, 1); - tstate->interp->threads.count--; + _Py_atomic_add_ssize(&tstate->interp->threads.count, -1); PyThreadState_Clear(tstate); _PyThreadState_DeleteCurrent(tstate); @@ -1520,7 +1520,7 @@ static PyObject * thread__count(PyObject *self, PyObject *Py_UNUSED(ignored)) { PyInterpreterState *interp = _PyInterpreterState_GET(); - return PyLong_FromLong(interp->threads.count); + return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count)); } PyDoc_STRVAR(_count_doc,