]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117657: Fixes a few small TSAN issues in dictobject (#118200)
authorDino Viehland <dinoviehland@meta.com>
Thu, 25 Apr 2024 15:53:29 +0000 (08:53 -0700)
committerGitHub <noreply@github.com>
Thu, 25 Apr 2024 15:53:29 +0000 (08:53 -0700)
Fixup TSAN errors for dict

Include/cpython/dictobject.h
Include/internal/pycore_object.h
Objects/dictobject.c
Tools/tsan/suppressions_free_threading.txt

index 35b6a822a0dfffd8c3bff01f3d2b6a6f38a3886b..3fd23b9313c45361aea981a7d6cae99ab8aa52c3 100644 (file)
@@ -56,7 +56,11 @@ static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
     PyDictObject *mp;
     assert(PyDict_Check(op));
     mp = _Py_CAST(PyDictObject*, op);
+#ifdef Py_GIL_DISABLED
+    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
+#else
     return mp->ma_used;
+#endif
 }
 #define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op))
 
index 88b052f4544b155a72a65965876776fc0d471790..7df8003196d8cc0860d993b8771e35786a8e5510 100644 (file)
@@ -688,7 +688,7 @@ static inline PyDictObject *
 _PyObject_GetManagedDict(PyObject *obj)
 {
     PyManagedDictPointer *dorv = _PyObject_ManagedDictPointer(obj);
-    return (PyDictObject *)FT_ATOMIC_LOAD_PTR_RELAXED(dorv->dict);
+    return (PyDictObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(dorv->dict);
 }
 
 static inline PyDictValues *
index 2644516bc3077069155f9af50d64d6af596d7b9e..afcf535f8c0a78aaa8f5198591cc4e996a50e60c 100644 (file)
@@ -1097,10 +1097,11 @@ compare_unicode_unicode(PyDictObject *mp, PyDictKeysObject *dk,
                         void *ep0, Py_ssize_t ix, PyObject *key, Py_hash_t hash)
 {
     PyDictUnicodeEntry *ep = &((PyDictUnicodeEntry *)ep0)[ix];
-    assert(ep->me_key != NULL);
-    assert(PyUnicode_CheckExact(ep->me_key));
-    if (ep->me_key == key ||
-            (unicode_get_hash(ep->me_key) == hash && unicode_eq(ep->me_key, key))) {
+    PyObject *ep_key = FT_ATOMIC_LOAD_PTR_RELAXED(ep->me_key);
+    assert(ep_key != NULL);
+    assert(PyUnicode_CheckExact(ep_key));
+    if (ep_key == key ||
+            (unicode_get_hash(ep_key) == hash && unicode_eq(ep_key, key))) {
         return 1;
     }
     return 0;
@@ -1761,10 +1762,12 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
         else {
             assert(old_value != NULL);
             if (DK_IS_UNICODE(mp->ma_keys)) {
-                DK_UNICODE_ENTRIES(mp->ma_keys)[ix].me_value = value;
+                PyDictUnicodeEntry *ep = &DK_UNICODE_ENTRIES(mp->ma_keys)[ix];
+                STORE_VALUE(ep, value);
             }
             else {
-                DK_ENTRIES(mp->ma_keys)[ix].me_value = value;
+                PyDictKeyEntry *ep = &DK_ENTRIES(mp->ma_keys)[ix];
+                STORE_VALUE(ep, value);
             }
         }
         mp->ma_version_tag = new_version;
@@ -1810,15 +1813,15 @@ insert_to_emptydict(PyInterpreterState *interp, PyDictObject *mp,
     if (unicode) {
         PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(newkeys);
         ep->me_key = key;
-        ep->me_value = value;
+        STORE_VALUE(ep, value);
     }
     else {
         PyDictKeyEntry *ep = DK_ENTRIES(newkeys);
         ep->me_key = key;
         ep->me_hash = hash;
-        ep->me_value = value;
+        STORE_VALUE(ep, value);
     }
-    mp->ma_used++;
+    FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, FT_ATOMIC_LOAD_SSIZE_RELAXED(mp->ma_used) + 1);
     mp->ma_version_tag = new_version;
     newkeys->dk_usable--;
     newkeys->dk_nentries++;
@@ -2510,7 +2513,7 @@ delitem_common(PyDictObject *mp, Py_hash_t hash, Py_ssize_t ix,
     Py_ssize_t hashpos = lookdict_index(mp->ma_keys, hash, ix);
     assert(hashpos >= 0);
 
-    mp->ma_used--;
+    FT_ATOMIC_STORE_SSIZE_RELAXED(mp->ma_used, FT_ATOMIC_LOAD_SSIZE(mp->ma_used) - 1);
     mp->ma_version_tag = new_version;
     if (_PyDict_HasSplitTable(mp)) {
         assert(old_value == mp->ma_values->values[ix]);
@@ -6895,7 +6898,7 @@ _PyObject_TryGetInstanceAttribute(PyObject *obj, PyObject *name, PyObject **attr
     }
 
 #ifdef Py_GIL_DISABLED
-    PyObject *value = _Py_atomic_load_ptr_relaxed(&values->values[ix]);
+    PyObject *value = _Py_atomic_load_ptr_acquire(&values->values[ix]);
     if (value == NULL || _Py_TryIncrefCompare(&values->values[ix], value)) {
         *attr = value;
         return true;
index aa954ca9b6c09cf7512dff72d5e43e44afe8b960..e4ca32bebc5a22be4cda6b040f71883a3961ca63 100644 (file)
@@ -28,9 +28,6 @@ race:_PyObject_GC_TRACK
 race:_PyParkingLot_Park
 race:_PyType_HasFeature
 race:assign_version_tag
-race:compare_unicode_unicode
-race:delitem_common
-race:dictresize
 race:gc_collect_main
 race:gc_restore_tid
 race:initialize_new_array