Skip to content

Commit 5da0280

Browse files
authored
gh-117657: Fixes a few small TSAN issues in dictobject (#118200)
Fixup TSAN errors for dict
1 parent cce5ae6 commit 5da0280

File tree

4 files changed

+19
-15
lines changed

4 files changed

+19
-15
lines changed

Include/cpython/dictobject.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,11 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
5656
PyDictObject *mp;
5757
assert(PyDict_Check(op));
5858
mp = _Py_CAST(PyDictObject*, op);
59+
#ifdef Py_GIL_DISABLED
60+
return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
61+
#else
5962
return mp->ma_used;
63+
#endif
6064
}
6165
#define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op))
6266

Include/internal/pycore_object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ static inline PyDictObject *
688688
_PyObject_GetManagedDict(PyObject *obj)
689689
{
690690
PyManagedDictPointer *dorv = _PyObject_ManagedDictPointer(obj);
691-
return (PyDictObject *)FT_ATOMIC_LOAD_PTR_RELAXED(dorv->dict);
691+
return (PyDictObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(dorv->dict);
692692
}
693693

694694
static inline PyDictValues *

Objects/dictobject.c

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,10 +1097,11 @@ compare_unicode_unicode(PyDictObject *mp, PyDictKeysObject *dk,
10971097
void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
10981098
{
10991099
PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
1100-
assert(ep->me_key != NULL);
1101-
assert(PyUnicode_CheckExact(ep->me_key));
1102-
if (ep->me_key == key ||
1103-
(unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
1100+
PyObject *ep_key = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key);
1101+
assert(ep_key != NULL);
1102+
assert(PyUnicode_CheckExact(ep_key));
1103+
if (ep_key == key ||
1104+
(unicode_get_hash(ep_key) == hash && unicode_eq(ep_key, key))) {
11041105
return 1;
11051106
}
11061107
return 0;
@@ -1761,10 +1762,12 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
17611762
else {
17621763
assert(old_value != NULL);
17631764
if (DK_IS_UNICODE(mp->ma_keys)) {
1764-
DK_UNICODE_ENTRIES(mp->ma_keys)[ix].me_value = value;
1765+
PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
1766+
STORE_VALUE(ep, value);
17651767
}
17661768
else {
1767-
DK_ENTRIES(mp->ma_keys)[ix].me_value = value;
1769+
PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
1770+
STORE_VALUE(ep, value);
17681771
}
17691772
}
17701773
mp->ma_version_tag = new_version;
@@ -1810,15 +1813,15 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
18101813
if (unicode) {
18111814
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(newkeys);
18121815
ep->me_key = key;
1813-
ep->me_value = value;
1816+
STORE_VALUE(ep, value);
18141817
}
18151818
else {
18161819
PyDictKeyEntry *ep = DK_ENTRIES(newkeys);
18171820
ep->me_key = key;
18181821
ep->me_hash = hash;
1819-
ep->me_value = value;
1822+
STORE_VALUE(ep, value);
18201823
}
1821-
mp->ma_used++;
1824+
FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, FT_ATOMIC_LOAD_SSIZE_RELAXED(mp->ma_used) + 1);
18221825
mp->ma_version_tag = new_version;
18231826
newkeys->dk_usable--;
18241827
newkeys->dk_nentries++;
@@ -2510,7 +2513,7 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
25102513
Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
25112514
assert(hashpos >= 0);
25122515

2513-
mp->ma_used--;
2516+
FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, FT_ATOMIC_LOAD_SSIZE(mp->ma_used) - 1);
25142517
mp->ma_version_tag = new_version;
25152518
if (_PyDict_HasSplitTable(mp)) {
25162519
assert(old_value == mp->ma_values->values[ix]);
@@ -6895,7 +6898,7 @@ _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr
68956898
}
68966899

68976900
#ifdef Py_GIL_DISABLED
6898-
PyObject *value = _Py_atomic_load_ptr_relaxed(&values->values[ix]);
6901+
PyObject *value = _Py_atomic_load_ptr_acquire(&values->values[ix]);
68996902
if (value == NULL || _Py_TryIncrefCompare(&values->values[ix], value)) {
69006903
*attr = value;
69016904
return true;

Tools/tsan/suppressions_free_threading.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ race:_PyObject_GC_TRACK
2828
race:_PyParkingLot_Park
2929
race:_PyType_HasFeature
3030
race:assign_version_tag
31-
race:compare_unicode_unicode
32-
race:delitem_common
33-
race:dictresize
3431
race:gc_collect_main
3532
race:gc_restore_tid
3633
race:initialize_new_array

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy