Under high thread concurrency in free-threaded builds, `_Py_Specialize_LoadGlobal` suffers from lock contention when acquiring the critical section mutexes for the `globals` and `builtins` dictionaries during bytecode specialization.
This PR skips LOAD_GLOBAL bytecode specialization if acquiring the two object mutexes would block.
--- /dev/null
+Reduced lock contention during LOAD_GLOBAL bytecode specialization under
+free threading.
PyObject *globals, PyObject *builtins,
_Py_CODEUNIT *instr, PyObject *name)
{
+#ifdef Py_GIL_DISABLED
+ if (PyMutex_IsLocked(&globals->ob_mutex) || PyMutex_IsLocked(&builtins->ob_mutex)) {
+ // Skip specialization if either dictionary is locked to avoid lock
+ // contention.
+ unspecialize(instr);
+ return;
+ }
+#endif
Py_BEGIN_CRITICAL_SECTION2(globals, builtins);
specialize_load_global_lock_held(globals, builtins, instr, name);
Py_END_CRITICAL_SECTION2();