Skip to content

Commit ed3e31d

Browse files
committed
gh-155628: Use a relaxed add for the dict shared-keys incref
An INCREF_KEYS may only run while the caller already keeps the keys alive: every dictkeys_incref call site holds either the dict's per-object lock while dk is its ma_keys (which is also required to replace ma_keys), or a strong reference chain such as the type's cached keys. The increment therefore cannot race with the final decref and needs no ordering. DECREF_KEYS is unchanged: the final decref must order the keys' contents before freeing them.
1 parent d7dd332 commit ed3e31d

1 file changed

Lines changed: 4 additions & 2 deletions

File tree

Objects/dictobject.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,10 @@ set_values(PyDictObject *mp, PyDictValues *values)
230230
#define ASSERT_KEYS_LOCKED(keys) assert(PyMutex_IsLocked(&keys->dk_mutex))
231231
#define LOAD_SHARED_KEY(key) _Py_atomic_load_ptr_acquire(&key)
232232
#define STORE_SHARED_KEY(key, value) _Py_atomic_store_ptr_release(&key, value)
233-
// Inc refs the keys object, giving the previous value
234-
#define INCREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, 1)
233+
// Inc refs the keys object, giving the previous value. Relaxed ordering
234+
// suffices: an incref may only run while the caller already keeps the keys
235+
// alive, and the final decref provides the ordering needed to free them.
236+
#define INCREF_KEYS(dk) _Py_atomic_add_ssize_relaxed(&dk->dk_refcnt, 1)
235237
// Dec refs the keys object, giving the previous value
236238
#define DECREF_KEYS(dk) _Py_atomic_add_ssize(&dk->dk_refcnt, -1)
237239
#define LOAD_KEYS_NENTRIES(keys) _Py_atomic_load_ssize_relaxed(&keys->dk_nentries)

0 commit comments

Comments
 (0)