gh-148393: Use atomic ops on _ma_watcher_tag in free threading build (gh-148397)

Fixes data races between dict mutation and watch/unwatch on the same dict.
This commit is contained in:
Sam Gross 2026-04-12 10:40:41 -04:00 committed by GitHub
parent 03d2f035d6
commit 3ab94d6842
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 44 additions and 6 deletions

View file

@ -119,14 +119,15 @@ static int
get_mutations(PyObject* dict) {
assert(PyDict_CheckExact(dict));
PyDictObject *d = (PyDictObject *)dict;
return (d->_ma_watcher_tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS)-1);
uint64_t tag = FT_ATOMIC_LOAD_UINT64_RELAXED(d->_ma_watcher_tag);
return (tag >> DICT_MAX_WATCHERS) & ((1 << DICT_WATCHED_MUTATION_BITS) - 1);
}
static void
increment_mutations(PyObject* dict) {
assert(PyDict_CheckExact(dict));
PyDictObject *d = (PyDictObject *)dict;
d->_ma_watcher_tag += (1 << DICT_MAX_WATCHERS);
FT_ATOMIC_ADD_UINT64(d->_ma_watcher_tag, (1 << DICT_MAX_WATCHERS));
}
/* The first two dict watcher IDs are reserved for CPython,