Mailing List Archive

gh-110481: Fix biased reference counting queue initialization. (#117271)
https://github.com/python/cpython/commit/8dbfdb2957a7baade3a88661517f163ad694c39f
commit: 8dbfdb2957a7baade3a88661517f163ad694c39f
branch: main
author: Sam Gross <colesbury@gmail.com>
committer: colesbury <colesbury@gmail.com>
date: 2024-03-28T09:28:39-04:00
summary:

gh-110481: Fix biased reference counting queue initialization. (#117271)

The biased reference counting queue must be initialized from the bound
(active) thread because it uses `_Py_ThreadId()` as the key in a hash
table.

files:
M Python/brc.c
M Python/pystate.c

diff --git a/Python/brc.c b/Python/brc.c
index b73c721e71aef6..8f87bc33007bcf 100644
--- a/Python/brc.c
+++ b/Python/brc.c
@@ -119,6 +119,8 @@ _Py_brc_merge_refcounts(PyThreadState *tstate)
struct _brc_thread_state *brc = &((_PyThreadStateImpl *)tstate)->brc;
struct _brc_bucket *bucket = get_bucket(tstate->interp, brc->tid);

+ assert(brc->tid == _Py_ThreadId());
+
// Append all objects into a local stack. We don't want to hold the lock
// while calling destructors.
PyMutex_Lock(&bucket->mutex);
@@ -142,11 +144,12 @@ void
_Py_brc_init_thread(PyThreadState *tstate)
{
struct _brc_thread_state *brc = &((_PyThreadStateImpl *)tstate)->brc;
- brc->tid = _Py_ThreadId();
+ uintptr_t tid = _Py_ThreadId();

// Add ourself to the hashtable
- struct _brc_bucket *bucket = get_bucket(tstate->interp, brc->tid);
+ struct _brc_bucket *bucket = get_bucket(tstate->interp, tid);
PyMutex_Lock(&bucket->mutex);
+ brc->tid = tid;
llist_insert_tail(&bucket->root, &brc->bucket_node);
PyMutex_Unlock(&bucket->mutex);
}
@@ -155,6 +158,13 @@ void
_Py_brc_remove_thread(PyThreadState *tstate)
{
struct _brc_thread_state *brc = &((_PyThreadStateImpl *)tstate)->brc;
+ if (brc->tid == 0) {
+ // The thread state may have been created, but never bound to a native
+ // thread and therefore never added to the hashtable.
+ assert(tstate->_status.bound == 0);
+ return;
+ }
+
struct _brc_bucket *bucket = get_bucket(tstate->interp, brc->tid);

// We need to fully process any objects to merge before removing ourself
diff --git a/Python/pystate.c b/Python/pystate.c
index 921e74ed5a9826..8489f53c6e3e34 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -261,6 +261,12 @@ bind_tstate(PyThreadState *tstate)
tstate->native_thread_id = PyThread_get_thread_native_id();
#endif

+#ifdef Py_GIL_DISABLED
+ // Initialize biased reference counting inter-thread queue. Note that this
+ // needs to be initialized from the active thread.
+ _Py_brc_init_thread(tstate);
+#endif
+
// mimalloc state needs to be initialized from the active thread.
tstate_mimalloc_bind(tstate);

@@ -1412,10 +1418,6 @@ init_threadstate(_PyThreadStateImpl *_tstate,
tstate->what_event = -1;
tstate->previous_executor = NULL;

-#ifdef Py_GIL_DISABLED
- // Initialize biased reference counting inter-thread queue
- _Py_brc_init_thread(tstate);
-#endif
llist_init(&_tstate->mem_free_queue);

if (interp->stoptheworld.requested || _PyRuntime.stoptheworld.requested) {

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-leave@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: list-python-checkins@lists.gossamer-threads.com