Make _PyDict_LoadGlobal threadsafe · python/cpython@548a7c2
@@ -1065,7 +1065,6 @@ compare_unicode_generic(PyDictObject *mp, PyDictKeysObject *dk,
10651065assert(ep->me_key != NULL);
10661066assert(PyUnicode_CheckExact(ep->me_key));
10671067assert(!PyUnicode_CheckExact(key));
1068-// TODO: Thread safety
1069106810701069if (unicode_get_hash(ep->me_key) == hash) {
10711070PyObject *startkey = ep->me_key;
@@ -1192,7 +1191,8 @@ _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **valu
11921191PyDictKeysObject *dk;
11931192DictKeysKind kind;
11941193Py_ssize_t ix;
1195-// TODO: Thread safety
1194+1195+_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);
11961196start:
11971197dk = mp->ma_keys;
11981198kind = dk->dk_kind;
@@ -1390,7 +1390,7 @@ dictkeys_generic_lookup_threadsafe(PyDictObject *mp, PyDictKeysObject* dk, PyObj
13901390return do_lookup(mp, dk, key, hash, compare_generic_threadsafe);
13911391}
139213921393-static Py_ssize_t
1393+Py_ssize_t
13941394_Py_dict_lookup_threadsafe(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr)
13951395{
13961396PyDictKeysObject *dk;
@@ -2343,11 +2343,12 @@ _PyDict_GetItemStringWithError(PyObject *v, const char *key)
23432343 * Raise an exception and return NULL if an error occurred (ex: computing the
23442344 * key hash failed, key comparison failed, ...). Return NULL if the key doesn't
23452345 * exist. Return the value if the key exists.
2346+ *
2347+ * Returns a new reference.
23462348 */
23472349PyObject *
23482350_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
23492351{
2350-// TODO: Thread safety
23512352Py_ssize_t ix;
23522353Py_hash_t hash;
23532354PyObject *value;
@@ -2358,17 +2359,31 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)
23582359return NULL;
23592360 }
236023612362+#ifdef Py_GIL_DISABLED
23612363/* namespace 1: globals */
2362-ix = _Py_dict_lookup(globals, key, hash, &value);
2364+ix = _Py_dict_lookup_threadsafe(globals, key, hash, &value);
23632365if (ix == DKIX_ERROR)
23642366return NULL;
23652367if (ix != DKIX_EMPTY && value != NULL)
23662368return value;
2367236923682370/* namespace 2: builtins */
2369-ix = _Py_dict_lookup(builtins, key, hash, &value);
2371+ix = _Py_dict_lookup_threadsafe(builtins, key, hash, &value);
23702372assert(ix >= 0 || value == NULL);
23712373return value;
2374+#else
2375+/* namespace 1: globals */
2376+ix = _Py_dict_lookup(globals, key, hash, &value);
2377+if (ix == DKIX_ERROR)
2378+return NULL;
2379+if (ix != DKIX_EMPTY && value != NULL)
2380+return Py_NewRef(value);
2381+2382+/* namespace 2: builtins */
2383+ix = _Py_dict_lookup(builtins, key, hash, &value);
2384+assert(ix >= 0 || value == NULL);
2385+return Py_XNewRef(value);
2386+#endif
23722387}
2373238823742389/* Consumes references to key and value */