summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-04-06 18:00:49 (GMT)
committerGitHub <noreply@github.com>2023-04-06 18:00:49 (GMT)
commit52e9b389a8773f485c3b0f1d62bf3cce4812d44d (patch)
tree98e9e102d60ce3e98fa7a7122a7489e7a8550334 /Python
parent23cf1e20a6470588fbc64483031ceeec7614dc56 (diff)
downloadcpython-52e9b389a8773f485c3b0f1d62bf3cce4812d44d.zip
cpython-52e9b389a8773f485c3b0f1d62bf3cce4812d44d.tar.gz
cpython-52e9b389a8773f485c3b0f1d62bf3cce4812d44d.tar.bz2
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.
Diffstat (limited to 'Python')
-rw-r--r--Python/pystate.c108
1 files changed, 48 insertions, 60 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 1e59a8c..d09c1d5 100644
--- a/Python/pystate.c
+++ b/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);