mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
gh-116322: Add Py_mod_gil module slot (#116882)
This PR adds the ability to enable the GIL if it was disabled at interpreter startup, and modifies the multi-phase module initialization path to enable the GIL when loading a module, unless that module's spec includes a slot indicating it can run safely without the GIL. PEP 703 called the constant for the slot `Py_mod_gil_not_used`; I went with `Py_MOD_GIL_NOT_USED` for consistency with gh-104148. A warning will be issued up to once per interpreter for the first GIL-using module that is loaded. If `-v` is given, a shorter message will be printed to stderr every time a GIL-using module is loaded (including the first one that issues a warning).
This commit is contained in:
parent
3e818afb9b
commit
c2627d6eea
123 changed files with 376 additions and 62 deletions
|
@ -249,6 +249,9 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
|
|||
}
|
||||
}
|
||||
m->md_def = module;
|
||||
#ifdef Py_GIL_DISABLE
|
||||
m->md_gil = Py_MOD_GIL_USED;
|
||||
#endif
|
||||
return (PyObject*)m;
|
||||
}
|
||||
|
||||
|
@ -261,6 +264,8 @@ PyModule_FromDefAndSpec2(PyModuleDef* def, PyObject *spec, int module_api_versio
|
|||
PyObject *m = NULL;
|
||||
int has_multiple_interpreters_slot = 0;
|
||||
void *multiple_interpreters = (void *)0;
|
||||
int has_gil_slot = 0;
|
||||
void *gil_slot = Py_MOD_GIL_USED;
|
||||
int has_execution_slots = 0;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
@ -315,6 +320,17 @@ PyModule_FromDefAndSpec2(PyModuleDef* def, PyObject *spec, int module_api_versio
|
|||
multiple_interpreters = cur_slot->value;
|
||||
has_multiple_interpreters_slot = 1;
|
||||
break;
|
||||
case Py_mod_gil:
|
||||
if (has_gil_slot) {
|
||||
PyErr_Format(
|
||||
PyExc_SystemError,
|
||||
"module %s has more than one 'gil' slot",
|
||||
name);
|
||||
goto error;
|
||||
}
|
||||
gil_slot = cur_slot->value;
|
||||
has_gil_slot = 1;
|
||||
break;
|
||||
default:
|
||||
assert(cur_slot->slot < 0 || cur_slot->slot > _Py_mod_LAST_SLOT);
|
||||
PyErr_Format(
|
||||
|
@ -374,6 +390,11 @@ PyModule_FromDefAndSpec2(PyModuleDef* def, PyObject *spec, int module_api_versio
|
|||
if (PyModule_Check(m)) {
|
||||
((PyModuleObject*)m)->md_state = NULL;
|
||||
((PyModuleObject*)m)->md_def = def;
|
||||
#ifdef Py_GIL_DISABLED
|
||||
((PyModuleObject*)m)->md_gil = gil_slot;
|
||||
#else
|
||||
(void)gil_slot;
|
||||
#endif
|
||||
} else {
|
||||
if (def->m_size > 0 || def->m_traverse || def->m_clear || def->m_free) {
|
||||
PyErr_Format(
|
||||
|
@ -415,6 +436,19 @@ error:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
int
|
||||
PyModule_ExperimentalSetGIL(PyObject *module, void *gil)
|
||||
{
|
||||
if (!PyModule_Check(module)) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
((PyModuleObject *)module)->md_gil = gil;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
PyModule_ExecDef(PyObject *module, PyModuleDef *def)
|
||||
{
|
||||
|
@ -470,6 +504,7 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def)
|
|||
}
|
||||
break;
|
||||
case Py_mod_multiple_interpreters:
|
||||
case Py_mod_gil:
|
||||
/* handled in PyModule_FromDefAndSpec2 */
|
||||
break;
|
||||
default:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue