Skip to content

Commit 8ed62ca

Browse files
committed
pystate: use _PyRawMutex for internal mutexes
This uses _PyRawMutex instead of PyThread_type_lock for a number of internal locks in PyRuntime.
1 parent 7a7aca0 commit 8ed62ca

File tree

5 files changed

+20
-134
lines changed

5 files changed

+20
-134
lines changed

‎Include/internal/pycore_runtime.h‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ extern "C" {
2929
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
3030

3131
struct _getargs_runtime_state {
32-
PyThread_type_lock mutex;
3332
struct _PyArg_Parser *static_parsers;
3433
};
3534

@@ -96,7 +95,7 @@ typedef struct pyruntimestate {
9695
struct _signals_runtime_state signals;
9796

9897
struct pyinterpreters {
99-
PyThread_type_lock mutex;
98+
_PyRawMutex mutex;
10099
/* The linked list of interpreters, newest first. */
101100
PyInterpreterState *head;
102101
/* The runtime's initial interpreter, which has a special role
@@ -115,7 +114,7 @@ typedef struct pyruntimestate {
115114
} interpreters;
116115
// XXX Remove this field once we have a tp_* slot.
117116
struct _xidregistry {
118-
PyThread_type_lock mutex;
117+
_PyRawMutex mutex;
119118
struct _xidregitem *head;
120119
} xidregistry;
121120

@@ -180,6 +179,10 @@ typedef struct pyruntimestate {
180179
PyInterpreterState _main_interpreter;
181180
} _PyRuntimeState;
182181

182+
#define HEAD_LOCK(runtime) \
183+
_PyRawMutex_lock(&(runtime)->interpreters.mutex)
184+
#define HEAD_UNLOCK(runtime) \
185+
_PyRawMutex_unlock(&(runtime)->interpreters.mutex)
183186

184187
/* other API */
185188

‎Include/internal/pycore_unicodeobject.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extern PyTypeObject _PyUnicodeASCIIIter_Type;
2626
/* other API */
2727

2828
struct _Py_unicode_runtime_ids {
29-
PyThread_type_lock lock;
29+
_PyMutex mutex;
3030
// next_index value must be preserved when Py_Initialize()/Py_Finalize()
3131
// is called multiple times: see _PyUnicode_FromId() implementation.
3232
Py_ssize_t next_index;

‎Objects/unicodeobject.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,7 @@ _PyUnicode_FromId(_Py_Identifier *id)
18581858
if (index < 0) {
18591859
struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_state.ids;
18601860

1861-
PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK);
1861+
_PyMutex_lock(&rt_ids->mutex);
18621862
// Check again to detect concurrent access. Another thread can have
18631863
// initialized the index while this thread waited for the lock.
18641864
index = _Py_atomic_size_get(&id->index);
@@ -1868,7 +1868,7 @@ _PyUnicode_FromId(_Py_Identifier *id)
18681868
rt_ids->next_index++;
18691869
_Py_atomic_size_set(&id->index, index);
18701870
}
1871-
PyThread_release_lock(rt_ids->lock);
1871+
_PyMutex_unlock(&rt_ids->mutex);
18721872
}
18731873
assert(index >= 0);
18741874

‎Python/ceval.c‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,6 @@
9797
#define _Py_atomic_load_relaxed_int32(ATOMIC_VAL) _Py_atomic_load_relaxed(ATOMIC_VAL)
9898
#endif
9999

100-
#define HEAD_LOCK(runtime) \
101-
PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
102-
#define HEAD_UNLOCK(runtime) \
103-
PyThread_release_lock((runtime)->interpreters.mutex)
104-
105100
/* Forward declarations */
106101
static PyObject *trace_call_function(
107102
PyThreadState *tstate, PyObject *callable, PyObject **stack,

‎Python/pystate.c‎

Lines changed: 11 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -63,59 +63,11 @@ _Py_COMP_DIAG_POP
6363
Py_DECL_THREAD PyThreadState *_Py_current_tstate;
6464

6565

66-
static int
67-
alloc_for_runtime(PyThread_type_lock *plock1, PyThread_type_lock *plock2,
68-
PyThread_type_lock *plock3, PyThread_type_lock *plock4)
69-
{
70-
/* Force default allocator, since _PyRuntimeState_Fini() must
71-
use the same allocator than this function. */
72-
PyMemAllocatorEx old_alloc;
73-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
74-
75-
PyThread_type_lock lock1 = PyThread_allocate_lock();
76-
if (lock1 == NULL) {
77-
return -1;
78-
}
79-
80-
PyThread_type_lock lock2 = PyThread_allocate_lock();
81-
if (lock2 == NULL) {
82-
PyThread_free_lock(lock1);
83-
return -1;
84-
}
85-
86-
PyThread_type_lock lock3 = PyThread_allocate_lock();
87-
if (lock3 == NULL) {
88-
PyThread_free_lock(lock1);
89-
PyThread_free_lock(lock2);
90-
return -1;
91-
}
92-
93-
PyThread_type_lock lock4 = PyThread_allocate_lock();
94-
if (lock4 == NULL) {
95-
PyThread_free_lock(lock1);
96-
PyThread_free_lock(lock2);
97-
PyThread_free_lock(lock3);
98-
return -1;
99-
}
100-
101-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
102-
103-
*plock1 = lock1;
104-
*plock2 = lock2;
105-
*plock3 = lock3;
106-
*plock4 = lock4;
107-
return 0;
108-
}
109-
11066
static void
11167
init_runtime(_PyRuntimeState *runtime,
11268
void *open_code_hook, void *open_code_userdata,
11369
_Py_AuditHookEntry *audit_hook_head,
114-
Py_ssize_t unicode_next_index,
115-
PyThread_type_lock unicode_ids_mutex,
116-
PyThread_type_lock interpreters_mutex,
117-
PyThread_type_lock xidregistry_mutex,
118-
PyThread_type_lock getargs_mutex)
70+
Py_ssize_t unicode_next_index)
11971
{
12072
if (runtime->_initialized) {
12173
Py_FatalError("runtime already initialized");
@@ -133,17 +85,10 @@ init_runtime(_PyRuntimeState *runtime,
13385

13486
PyPreConfig_InitPythonConfig(&runtime->preconfig);
13587

136-
runtime->interpreters.mutex = interpreters_mutex;
137-
138-
runtime->xidregistry.mutex = xidregistry_mutex;
139-
140-
runtime->getargs.mutex = getargs_mutex;
141-
14288
// Set it to the ID of the main thread of the main interpreter.
14389
runtime->main_thread = PyThread_get_thread_ident();
14490

14591
runtime->unicode_state.ids.next_index = unicode_next_index;
146-
runtime->unicode_state.ids.lock = unicode_ids_mutex;
14792

14893
runtime->_initialized = 1;
14994
}
@@ -161,41 +106,20 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
161106
// is called multiple times.
162107
Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index;
163108

164-
PyThread_type_lock lock1, lock2, lock3, lock4;
165-
if (alloc_for_runtime(&lock1, &lock2, &lock3, &lock4) != 0) {
166-
return _PyStatus_NO_MEMORY();
167-
}
168-
169109
if (runtime->_initialized) {
170110
// Py_Initialize() must be running again.
171111
// Reset to _PyRuntimeState_INIT.
172112
memcpy(runtime, &initial, sizeof(*runtime));
173113
}
174114
init_runtime(runtime, open_code_hook, open_code_userdata, audit_hook_head,
175-
unicode_next_index, lock1, lock2, lock3, lock4);
115+
unicode_next_index);
176116

177117
return _PyStatus_OK();
178118
}
179119

180120
void
181121
_PyRuntimeState_Fini(_PyRuntimeState *runtime)
182122
{
183-
/* Force the allocator used by _PyRuntimeState_Init(). */
184-
PyMemAllocatorEx old_alloc;
185-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
186-
#define FREE_LOCK(LOCK) \
187-
if (LOCK != NULL) { \
188-
PyThread_free_lock(LOCK); \
189-
LOCK = NULL; \
190-
}
191-
192-
FREE_LOCK(runtime->interpreters.mutex);
193-
FREE_LOCK(runtime->xidregistry.mutex);
194-
FREE_LOCK(runtime->unicode_state.ids.lock);
195-
FREE_LOCK(runtime->getargs.mutex);
196-
197-
#undef FREE_LOCK
198-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
199123
}
200124

201125
#ifdef HAVE_FORK
@@ -207,27 +131,14 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
207131
// This was initially set in _PyRuntimeState_Init().
208132
runtime->main_thread = PyThread_get_thread_ident();
209133

210-
/* Force default allocator, since _PyRuntimeState_Fini() must
211-
use the same allocator than this function. */
212-
PyMemAllocatorEx old_alloc;
213-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
214-
215-
int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex);
216-
int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex);
217-
int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_state.ids.lock);
218-
int reinit_getargs = _PyThread_at_fork_reinit(&runtime->getargs.mutex);
219-
220-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
134+
memset(&runtime->interpreters.mutex, 0, sizeof(runtime->interpreters.mutex));
135+
memset(&runtime->xidregistry.mutex, 0, sizeof(runtime->xidregistry.mutex));
221136

222137
/* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does
223138
* not force the default allocator. */
224139
int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex);
225140

226-
if (reinit_interp < 0
227-
|| reinit_main_id < 0
228-
|| reinit_xidregistry < 0
229-
|| reinit_unicode_ids < 0
230-
|| reinit_getargs < 0)
141+
if (reinit_main_id < 0)
231142
{
232143
return _PyStatus_ERR("Failed to reinitialize runtime locks");
233144

@@ -236,11 +147,6 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
236147
}
237148
#endif
238149

239-
#define HEAD_LOCK(runtime) \
240-
PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
241-
#define HEAD_UNLOCK(runtime) \
242-
PyThread_release_lock((runtime)->interpreters.mutex)
243-
244150
/* Forward declaration */
245151
static void _PyGILState_NoteThreadState(
246152
struct _gilstate_runtime_state *gilstate, PyThreadState* tstate);
@@ -284,24 +190,6 @@ _PyInterpreterState_Enable(_PyRuntimeState *runtime)
284190
{
285191
struct pyinterpreters *interpreters = &runtime->interpreters;
286192
interpreters->next_id = 0;
287-
288-
/* Py_Finalize() calls _PyRuntimeState_Fini() which clears the mutex.
289-
Create a new mutex if needed. */
290-
if (interpreters->mutex == NULL) {
291-
/* Force default allocator, since _PyRuntimeState_Fini() must
292-
use the same allocator than this function. */
293-
PyMemAllocatorEx old_alloc;
294-
_PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
295-
296-
interpreters->mutex = PyThread_allocate_lock();
297-
298-
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
299-
300-
if (interpreters->mutex == NULL) {
301-
return _PyStatus_ERR("Can't initialize threads for interpreter");
302-
}
303-
}
304-
305193
return _PyStatus_OK();
306194
}
307195

@@ -2168,12 +2056,12 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
21682056
}
21692057

21702058
struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;
2171-
PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);
2059+
_PyRawMutex_lock(&xidregistry->mutex);
21722060
if (xidregistry->head == NULL) {
21732061
_register_builtins_for_crossinterpreter_data(xidregistry);
21742062
}
21752063
int res = _xidregistry_add_type(xidregistry, cls, getdata);
2176-
PyThread_release_lock(xidregistry->mutex);
2064+
_PyRawMutex_unlock(&xidregistry->mutex);
21772065
return res;
21782066
}
21792067

@@ -2182,13 +2070,13 @@ _PyCrossInterpreterData_UnregisterClass(PyTypeObject *cls)
21822070
{
21832071
int res = 0;
21842072
struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;
2185-
PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);
2073+
_PyRawMutex_lock(&xidregistry->mutex);
21862074
struct _xidregitem *matched = _xidregistry_find_type(xidregistry, cls);
21872075
if (matched != NULL) {
21882076
(void)_xidregistry_remove_entry(xidregistry, matched);
21892077
res = 1;
21902078
}
2191-
PyThread_release_lock(xidregistry->mutex);
2079+
_PyRawMutex_unlock(&xidregistry->mutex);
21922080
return res;
21932081
}
21942082

@@ -2202,14 +2090,14 @@ _PyCrossInterpreterData_Lookup(PyObject *obj)
22022090
{
22032091
struct _xidregistry *xidregistry = &_PyRuntime.xidregistry ;
22042092
PyObject *cls = PyObject_Type(obj);
2205-
PyThread_acquire_lock(xidregistry->mutex, WAIT_LOCK);
2093+
_PyRawMutex_lock(&xidregistry->mutex);
22062094
if (xidregistry->head == NULL) {
22072095
_register_builtins_for_crossinterpreter_data(xidregistry);
22082096
}
22092097
struct _xidregitem *matched = _xidregistry_find_type(xidregistry,
22102098
(PyTypeObject *)cls);
22112099
Py_DECREF(cls);
2212-
PyThread_release_lock(xidregistry->mutex);
2100+
_PyRawMutex_unlock(&xidregistry->mutex);
22132101
return matched != NULL ? matched->getdata : NULL;
22142102
}
22152103

0 commit comments

Comments
 (0)