mirror of https://github.com/python/cpython
gh-100227: Use an Array for _PyRuntime's Set of Locks During Init (gh-103315)
This cleans things up a bit and simplifies adding new granular global locks.
This commit is contained in:
parent
23cf1e20a6
commit
52e9b389a8
108
Python/pystate.c
108
Python/pystate.c
|
@ -354,47 +354,29 @@ _Py_COMP_DIAG_IGNORE_DEPR_DECLS
|
|||
static const _PyRuntimeState initial = _PyRuntimeState_INIT(_PyRuntime);
|
||||
_Py_COMP_DIAG_POP
|
||||
|
||||
#define NUMLOCKS 4
|
||||
|
||||
static int
|
||||
alloc_for_runtime(PyThread_type_lock *plock1, PyThread_type_lock *plock2,
|
||||
PyThread_type_lock *plock3, PyThread_type_lock *plock4)
|
||||
alloc_for_runtime(PyThread_type_lock locks[NUMLOCKS])
|
||||
{
|
||||
/* Force default allocator, since _PyRuntimeState_Fini() must
|
||||
use the same allocator than this function. */
|
||||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
PyThread_type_lock lock1 = PyThread_allocate_lock();
|
||||
if (lock1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThread_type_lock lock2 = PyThread_allocate_lock();
|
||||
if (lock2 == NULL) {
|
||||
PyThread_free_lock(lock1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThread_type_lock lock3 = PyThread_allocate_lock();
|
||||
if (lock3 == NULL) {
|
||||
PyThread_free_lock(lock1);
|
||||
PyThread_free_lock(lock2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyThread_type_lock lock4 = PyThread_allocate_lock();
|
||||
if (lock4 == NULL) {
|
||||
PyThread_free_lock(lock1);
|
||||
PyThread_free_lock(lock2);
|
||||
PyThread_free_lock(lock3);
|
||||
return -1;
|
||||
for (int i = 0; i < NUMLOCKS; i++) {
|
||||
PyThread_type_lock lock = PyThread_allocate_lock();
|
||||
if (lock == NULL) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
PyThread_free_lock(locks[j]);
|
||||
locks[j] = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
locks[i] = lock;
|
||||
}
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
*plock1 = lock1;
|
||||
*plock2 = lock2;
|
||||
*plock3 = lock3;
|
||||
*plock4 = lock4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -403,10 +385,7 @@ init_runtime(_PyRuntimeState *runtime,
|
|||
void *open_code_hook, void *open_code_userdata,
|
||||
_Py_AuditHookEntry *audit_hook_head,
|
||||
Py_ssize_t unicode_next_index,
|
||||
PyThread_type_lock unicode_ids_mutex,
|
||||
PyThread_type_lock interpreters_mutex,
|
||||
PyThread_type_lock xidregistry_mutex,
|
||||
PyThread_type_lock getargs_mutex)
|
||||
PyThread_type_lock locks[NUMLOCKS])
|
||||
{
|
||||
if (runtime->_initialized) {
|
||||
Py_FatalError("runtime already initialized");
|
||||
|
@ -424,17 +403,21 @@ init_runtime(_PyRuntimeState *runtime,
|
|||
|
||||
PyPreConfig_InitPythonConfig(&runtime->preconfig);
|
||||
|
||||
runtime->interpreters.mutex = interpreters_mutex;
|
||||
|
||||
runtime->xidregistry.mutex = xidregistry_mutex;
|
||||
|
||||
runtime->getargs.mutex = getargs_mutex;
|
||||
PyThread_type_lock *lockptrs[NUMLOCKS] = {
|
||||
&runtime->interpreters.mutex,
|
||||
&runtime->xidregistry.mutex,
|
||||
&runtime->getargs.mutex,
|
||||
&runtime->unicode_state.ids.lock,
|
||||
};
|
||||
for (int i = 0; i < NUMLOCKS; i++) {
|
||||
assert(locks[i] != NULL);
|
||||
*lockptrs[i] = locks[i];
|
||||
}
|
||||
|
||||
// Set it to the ID of the main thread of the main interpreter.
|
||||
runtime->main_thread = PyThread_get_thread_ident();
|
||||
|
||||
runtime->unicode_state.ids.next_index = unicode_next_index;
|
||||
runtime->unicode_state.ids.lock = unicode_ids_mutex;
|
||||
|
||||
runtime->_initialized = 1;
|
||||
}
|
||||
|
@ -452,8 +435,8 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
|
|||
// is called multiple times.
|
||||
Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index;
|
||||
|
||||
PyThread_type_lock lock1, lock2, lock3, lock4;
|
||||
if (alloc_for_runtime(&lock1, &lock2, &lock3, &lock4) != 0) {
|
||||
PyThread_type_lock locks[NUMLOCKS];
|
||||
if (alloc_for_runtime(locks) != 0) {
|
||||
return _PyStatus_NO_MEMORY();
|
||||
}
|
||||
|
||||
|
@ -474,7 +457,7 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
|
|||
}
|
||||
|
||||
init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head,
|
||||
unicode_next_index, lock1, lock2, lock3, lock4);
|
||||
unicode_next_index, locks);
|
||||
|
||||
return _PyStatus_OK();
|
||||
}
|
||||
|
@ -504,10 +487,15 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
|
|||
LOCK = NULL; \
|
||||
}
|
||||
|
||||
FREE_LOCK(runtime->interpreters.mutex);
|
||||
FREE_LOCK(runtime->xidregistry.mutex);
|
||||
FREE_LOCK(runtime->unicode_state.ids.lock);
|
||||
FREE_LOCK(runtime->getargs.mutex);
|
||||
PyThread_type_lock *lockptrs[NUMLOCKS] = {
|
||||
&runtime->interpreters.mutex,
|
||||
&runtime->xidregistry.mutex,
|
||||
&runtime->getargs.mutex,
|
||||
&runtime->unicode_state.ids.lock,
|
||||
};
|
||||
for (int i = 0; i < NUMLOCKS; i++) {
|
||||
FREE_LOCK(*lockptrs[i]);
|
||||
}
|
||||
|
||||
#undef FREE_LOCK
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
@ -527,25 +515,25 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
|
|||
PyMemAllocatorEx old_alloc;
|
||||
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
|
||||
int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
|
||||
int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_state.ids.lock);
|
||||
int reinit_getargs = _PyThread_at_fork_reinit(&runtime->getargs.mutex);
|
||||
PyThread_type_lock *lockptrs[NUMLOCKS] = {
|
||||
&runtime->interpreters.mutex,
|
||||
&runtime->xidregistry.mutex,
|
||||
&runtime->getargs.mutex,
|
||||
&runtime->unicode_state.ids.lock,
|
||||
};
|
||||
int reinit_err = 0;
|
||||
for (int i = 0; i < NUMLOCKS; i++) {
|
||||
reinit_err += _PyThread_at_fork_reinit(lockptrs[i]);
|
||||
}
|
||||
|
||||
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
|
||||
|
||||
/* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does
|
||||
* not force the default allocator. */
|
||||
int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
|
||||
reinit_err += _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
|
||||
|
||||
if (reinit_interp < 0
|
||||
|| reinit_main_id < 0
|
||||
|| reinit_xidregistry < 0
|
||||
|| reinit_unicode_ids < 0
|
||||
|| reinit_getargs < 0)
|
||||
{
|
||||
if (reinit_err < 0) {
|
||||
return _PyStatus_ERR("Failed to reinitialize runtime locks");
|
||||
|
||||
}
|
||||
|
||||
PyStatus status = gilstate_tss_reinit(runtime);
|
||||
|
|
Loading…
Reference in New Issue