summaryrefslogtreecommitdiffstats
path: root/Include
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2023-12-07 19:33:40 (GMT)
committerGitHub <noreply@github.com>2023-12-07 19:33:40 (GMT)
commitcf6110ba1337cb67e5867d86e7c0e8d923a5bc8d (patch)
treeab8393161d5ce01479bfb03dce874ab52246d28f /Include
parentdb460735af7503984d1b7d878069722db44b11e8 (diff)
downloadcpython-cf6110ba1337cb67e5867d86e7c0e8d923a5bc8d.zip
cpython-cf6110ba1337cb67e5867d86e7c0e8d923a5bc8d.tar.gz
cpython-cf6110ba1337cb67e5867d86e7c0e8d923a5bc8d.tar.bz2
gh-111924: Use PyMutex for Runtime-global Locks. (gh-112207)
This replaces some usages of PyThread_type_lock with PyMutex, which does not require memory allocation to initialize. This simplifies some of the runtime initialization and is also one step towards avoiding changing the default raw memory allocator during initialize/finalization, which can be non-thread-safe in some circumstances.
Diffstat (limited to 'Include')
-rw-r--r--Include/internal/pycore_atexit.h5
-rw-r--r--Include/internal/pycore_ceval.h3
-rw-r--r--Include/internal/pycore_ceval_state.h3
-rw-r--r--Include/internal/pycore_crossinterp.h3
-rw-r--r--Include/internal/pycore_import.h3
-rw-r--r--Include/internal/pycore_lock.h17
-rw-r--r--Include/internal/pycore_pymem.h5
-rw-r--r--Include/internal/pycore_pystate.h4
-rw-r--r--Include/internal/pycore_runtime.h4
-rw-r--r--Include/internal/pycore_unicodeobject.h3
10 files changed, 38 insertions, 12 deletions
diff --git a/Include/internal/pycore_atexit.h b/Include/internal/pycore_atexit.h
index 3966df7..4dcda8f 100644
--- a/Include/internal/pycore_atexit.h
+++ b/Include/internal/pycore_atexit.h
@@ -1,5 +1,8 @@
#ifndef Py_INTERNAL_ATEXIT_H
#define Py_INTERNAL_ATEXIT_H
+
+#include "pycore_lock.h" // PyMutex
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -15,7 +18,7 @@ extern "C" {
typedef void (*atexit_callbackfunc)(void);
struct _atexit_runtime_state {
- PyThread_type_lock mutex;
+ PyMutex mutex;
#define NEXITFUNCS 32
atexit_callbackfunc callbacks[NEXITFUNCS];
int ncallbacks;
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 3f7ac92..64fb403 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -41,8 +41,7 @@ PyAPI_FUNC(int) _PyEval_MakePendingCalls(PyThreadState *);
#endif
extern void _Py_FinishPendingCalls(PyThreadState *tstate);
-extern void _PyEval_InitState(PyInterpreterState *, PyThread_type_lock);
-extern void _PyEval_FiniState(struct _ceval_state *ceval);
+extern void _PyEval_InitState(PyInterpreterState *);
extern void _PyEval_SignalReceived(PyInterpreterState *interp);
// bitwise flags:
diff --git a/Include/internal/pycore_ceval_state.h b/Include/internal/pycore_ceval_state.h
index 072bbcd..2873898 100644
--- a/Include/internal/pycore_ceval_state.h
+++ b/Include/internal/pycore_ceval_state.h
@@ -8,6 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_lock.h" // PyMutex
#include "pycore_gil.h" // struct _gil_runtime_state
@@ -15,7 +16,7 @@ typedef int (*_Py_pending_call_func)(void *);
struct _pending_calls {
int busy;
- PyThread_type_lock lock;
+ PyMutex mutex;
/* Request for running pending calls. */
int32_t calls_to_do;
#define NPENDINGCALLS 32
diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h
index ec9dac9..2e6d09a 100644
--- a/Include/internal/pycore_crossinterp.h
+++ b/Include/internal/pycore_crossinterp.h
@@ -8,6 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_lock.h" // PyMutex
#include "pycore_pyerrors.h"
@@ -128,7 +129,7 @@ struct _xidregitem {
struct _xidregistry {
int global; /* builtin types or heap types */
int initialized;
- PyThread_type_lock mutex;
+ PyMutex mutex;
struct _xidregitem *head;
};
diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h
index 117e46b..c84f87a 100644
--- a/Include/internal/pycore_import.h
+++ b/Include/internal/pycore_import.h
@@ -9,6 +9,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_lock.h" // PyMutex
#include "pycore_hashtable.h" // _Py_hashtable_t
#include "pycore_time.h" // _PyTime_t
@@ -47,7 +48,7 @@ struct _import_runtime_state {
Py_ssize_t last_module_index;
struct {
/* A lock to guard the cache. */
- PyThread_type_lock mutex;
+ PyMutex mutex;
/* The actual cache of (filename, name, PyModuleDef) for modules.
Only legacy (single-phase init) extension modules are added
and only if they support multiple initialization (m_size >- 0)
diff --git a/Include/internal/pycore_lock.h b/Include/internal/pycore_lock.h
index f135cbb..03ad1c9 100644
--- a/Include/internal/pycore_lock.h
+++ b/Include/internal/pycore_lock.h
@@ -92,6 +92,13 @@ PyMutex_IsLocked(PyMutex *m)
return (_Py_atomic_load_uint8(&m->v) & _Py_LOCKED) != 0;
}
+// Re-initializes the mutex after a fork to the unlocked state.
+static inline void
+_PyMutex_at_fork_reinit(PyMutex *m)
+{
+ memset(m, 0, sizeof(*m));
+}
+
typedef enum _PyLockFlags {
// Do not detach/release the GIL when waiting on the lock.
_Py_LOCK_DONT_DETACH = 0,
@@ -108,6 +115,16 @@ typedef enum _PyLockFlags {
extern PyLockStatus
_PyMutex_LockTimed(PyMutex *m, _PyTime_t timeout_ns, _PyLockFlags flags);
+// Lock a mutex with aditional options. See _PyLockFlags for details.
+static inline void
+PyMutex_LockFlags(PyMutex *m, _PyLockFlags flags)
+{
+ uint8_t expected = _Py_UNLOCKED;
+ if (!_Py_atomic_compare_exchange_uint8(&m->v, &expected, _Py_LOCKED)) {
+ _PyMutex_LockTimed(m, -1, flags);
+ }
+}
+
// Unlock a mutex, returns 0 if the mutex is not locked (used for improved
// error messages).
extern int _PyMutex_TryUnlock(PyMutex *m);
diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h
index 6b51137..8631ca3 100644
--- a/Include/internal/pycore_pymem.h
+++ b/Include/internal/pycore_pymem.h
@@ -1,5 +1,8 @@
#ifndef Py_INTERNAL_PYMEM_H
#define Py_INTERNAL_PYMEM_H
+
+#include "pycore_lock.h" // PyMutex
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -30,7 +33,7 @@ typedef struct {
} debug_alloc_api_t;
struct _pymem_allocators {
- PyThread_type_lock mutex;
+ PyMutex mutex;
struct {
PyMemAllocatorEx raw;
PyMemAllocatorEx mem;
diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h
index 7fa952e..c031a38 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -220,9 +220,9 @@ PyAPI_FUNC(int) _PyState_AddModule(
extern int _PyOS_InterruptOccurred(PyThreadState *tstate);
#define HEAD_LOCK(runtime) \
- PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
+ PyMutex_LockFlags(&(runtime)->interpreters.mutex, _Py_LOCK_DONT_DETACH)
#define HEAD_UNLOCK(runtime) \
- PyThread_release_lock((runtime)->interpreters.mutex)
+ PyMutex_Unlock(&(runtime)->interpreters.mutex)
// Get the configuration of the current interpreter.
// The caller must hold the GIL.
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 3674372..e334829 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -173,7 +173,7 @@ typedef struct pyruntimestate {
unsigned long _finalizing_id;
struct pyinterpreters {
- PyThread_type_lock mutex;
+ PyMutex mutex;
/* The linked list of interpreters, newest first. */
PyInterpreterState *head;
/* The runtime's initial interpreter, which has a special role
@@ -234,7 +234,7 @@ typedef struct pyruntimestate {
Py_OpenCodeHookFunction open_code_hook;
void *open_code_userdata;
struct {
- PyThread_type_lock mutex;
+ PyMutex mutex;
_Py_AuditHookEntry *head;
} audit_hooks;
diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h
index a0d00af..7ee5401 100644
--- a/Include/internal/pycore_unicodeobject.h
+++ b/Include/internal/pycore_unicodeobject.h
@@ -8,6 +8,7 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+#include "pycore_lock.h" // PyMutex
#include "pycore_fileutils.h" // _Py_error_handler
#include "pycore_identifier.h" // _Py_Identifier
#include "pycore_ucnhash.h" // _PyUnicode_Name_CAPI
@@ -277,7 +278,7 @@ extern PyTypeObject _PyUnicodeASCIIIter_Type;
/* --- Other API ---------------------------------------------------------- */
struct _Py_unicode_runtime_ids {
- PyThread_type_lock lock;
+ PyMutex mutex;
// next_index value must be preserved when Py_Initialize()/Py_Finalize()
// is called multiple times: see _PyUnicode_FromId() implementation.
Py_ssize_t next_index;