Make _PyDict_LoadGlobal threadsafe · python/cpython@548a7c2

@@ -1065,7 +1065,6 @@ compare_unicode_generic(PyDictObject *mp, PyDictKeysObject *dk,

10651065

assert(ep->me_key != NULL);

10661066

assert(PyUnicode_CheckExact(ep->me_key));

10671067

assert(!PyUnicode_CheckExact(key));

1068-

// TODO: Thread safety

1069106810701069

if (unicode_get_hash(ep->me_key) == hash) {

10711070

PyObject *startkey = ep->me_key;

@@ -1192,7 +1191,8 @@ _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **valu

11921191

PyDictKeysObject *dk;

11931192

DictKeysKind kind;

11941193

Py_ssize_t ix;

1195-

// TODO: Thread safety

1194+1195+

_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(mp);

11961196

start:

11971197

dk = mp->ma_keys;

11981198

kind = dk->dk_kind;

@@ -1390,7 +1390,7 @@ dictkeys_generic_lookup_threadsafe(PyDictObject *mp, PyDictKeysObject* dk, PyObj

13901390

return 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

{

13961396

PyDictKeysObject *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

*/

23472349

PyObject *

23482350

_PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)

23492351

{

2350-

// TODO: Thread safety

23512352

Py_ssize_t ix;

23522353

Py_hash_t hash;

23532354

PyObject *value;

@@ -2358,17 +2359,31 @@ _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject *builtins, PyObject *key)

23582359

return 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);

23632365

if (ix == DKIX_ERROR)

23642366

return NULL;

23652367

if (ix != DKIX_EMPTY && value != NULL)

23662368

return value;

2367236923682370

/* namespace 2: builtins */

2369-

ix = _Py_dict_lookup(builtins, key, hash, &value);

2371+

ix = _Py_dict_lookup_threadsafe(builtins, key, hash, &value);

23702372

assert(ix >= 0 || value == NULL);

23712373

return 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 */