summaryrefslogtreecommitdiffstats
path: root/Include/cpython
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-06-20 16:00:25 (GMT)
committerGitHub <noreply@github.com>2024-06-20 16:00:25 (GMT)
commit3cb6c4cd60bec1acbcd960f5e7bd65f78152dbdd (patch)
treef5b72124507a3c8ea7e5938bdb2cdb7563ca1ac1 /Include/cpython
parent7c7aa5a99cce256ff726654038092a333a1f0531 (diff)
downloadcpython-3cb6c4cd60bec1acbcd960f5e7bd65f78152dbdd.zip
cpython-3cb6c4cd60bec1acbcd960f5e7bd65f78152dbdd.tar.gz
cpython-3cb6c4cd60bec1acbcd960f5e7bd65f78152dbdd.tar.bz2
[3.13] gh-117511: Make PyMutex public in the non-limited API (GH-117731) (#120800)
(cherry picked from commit 3af7263037de1d0ef63b070fc7bfc2cf042eaebe)
Diffstat (limited to 'Include/cpython')
-rw-r--r--Include/cpython/lock.h63
-rw-r--r--Include/cpython/weakrefobject.h2
2 files changed, 64 insertions, 1 deletions
diff --git a/Include/cpython/lock.h b/Include/cpython/lock.h
new file mode 100644
index 0000000..8ee03e8
--- /dev/null
+++ b/Include/cpython/lock.h
@@ -0,0 +1,63 @@
+#ifndef Py_CPYTHON_LOCK_H
+# error "this header file must not be included directly"
+#endif
+
+#define _Py_UNLOCKED 0
+#define _Py_LOCKED 1
+
+// A mutex that occupies one byte. The lock can be zero initialized to
+// represent the unlocked state.
+//
+// Typical initialization:
+// PyMutex m = (PyMutex){0};
+//
+// Or initialize as global variables:
+// static PyMutex m;
+//
+// Typical usage:
+// PyMutex_Lock(&m);
+// ...
+// PyMutex_Unlock(&m);
+//
+// The contents of the PyMutex are not part of the public API, but are
+// described to aid in understanding the implementation and debugging. Only
+// the two least significant bits are used. The remaining bits are always zero:
+// 0b00: unlocked
+// 0b01: locked
+// 0b10: unlocked and has parked threads
+// 0b11: locked and has parked threads
+typedef struct PyMutex {
+ uint8_t _bits; // (private)
+} PyMutex;
+
+// exported function for locking the mutex
+PyAPI_FUNC(void) PyMutex_Lock(PyMutex *m);
+
+// exported function for unlocking the mutex
+PyAPI_FUNC(void) PyMutex_Unlock(PyMutex *m);
+
+// Locks the mutex.
+//
+// If the mutex is currently locked, the calling thread will be parked until
+// the mutex is unlocked. If the current thread holds the GIL, then the GIL
+// will be released while the thread is parked.
+static inline void
+_PyMutex_Lock(PyMutex *m)
+{
+ uint8_t expected = _Py_UNLOCKED;
+ if (!_Py_atomic_compare_exchange_uint8(&m->_bits, &expected, _Py_LOCKED)) {
+ PyMutex_Lock(m);
+ }
+}
+#define PyMutex_Lock _PyMutex_Lock
+
+// Unlocks the mutex.
+static inline void
+_PyMutex_Unlock(PyMutex *m)
+{
+ uint8_t expected = _Py_LOCKED;
+ if (!_Py_atomic_compare_exchange_uint8(&m->_bits, &expected, _Py_UNLOCKED)) {
+ PyMutex_Unlock(m);
+ }
+}
+#define PyMutex_Unlock _PyMutex_Unlock
diff --git a/Include/cpython/weakrefobject.h b/Include/cpython/weakrefobject.h
index dcca166..28acf72 100644
--- a/Include/cpython/weakrefobject.h
+++ b/Include/cpython/weakrefobject.h
@@ -36,7 +36,7 @@ struct _PyWeakReference {
* Normally this can be derived from wr_object, but in some cases we need
* to lock after wr_object has been set to Py_None.
*/
- struct _PyMutex *weakrefs_lock;
+ PyMutex *weakrefs_lock;
#endif
};