https://github.com/python/cpython/commit/8e43b130f7b27657a8bb775e398c0dce325b4741
commit: 8e43b130f7b27657a8bb775e398c0dce325b4741
branch: 3.14
author: Hugo van Kemenade <[email protected]>
committer: hugovk <[email protected]>
date: 2025-07-22T12:48:08+03:00
summary:

[3.14] gh-134009: Expose `PyMutex_IsLocked` in the public C API (gh-134365) 
(#136971)

Co-authored-by: Sam Gross <[email protected]>

files:
A Misc/NEWS.d/next/C_API/2025-05-20-17-13-51.gh-issue-134009.CpCmry.rst
M Doc/c-api/init.rst
M Doc/whatsnew/3.14.rst
M Include/cpython/lock.h
M Include/internal/pycore_lock.h
M Python/lock.c

diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
index 51e9e6c352f0e4..2e255a8781c353 100644
--- a/Doc/c-api/init.rst
+++ b/Doc/c-api/init.rst
@@ -2441,6 +2441,18 @@ The C-API provides a basic mutual exclusion lock.
 
    .. versionadded:: 3.13
 
+.. c:function:: int PyMutex_IsLocked(PyMutex *m)
+
+   Returns non-zero if the mutex *m* is currently locked, zero otherwise.
+
+   .. note::
+
+      This function is intended for use in assertions and debugging only and
+      should not be used to make concurrency control decisions, as the lock
+      state may change immediately after the check.
+
+   .. versionadded:: 3.14
+
 .. _python-critical-section-api:
 
 Python Critical Section API
diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst
index 630d011ffbbd1f..2906828e05d229 100644
--- a/Doc/whatsnew/3.14.rst
+++ b/Doc/whatsnew/3.14.rst
@@ -3027,6 +3027,7 @@ Porting to Python 3.14
   * ``_PyLong_IsPositive()``: :c:func:`PyLong_IsPositive`
   * ``_PyLong_IsZero()``: :c:func:`PyLong_IsZero`
   * ``_PyLong_Sign()``: :c:func:`PyLong_GetSign`
+  * ``_PyMutex_IsLocked()`` : :c:func:`PyMutex_IsLocked`
   * ``_PyUnicodeWriter_Dealloc()``: :c:func:`PyUnicodeWriter_Discard`
   * ``_PyUnicodeWriter_Finish()``: :c:func:`PyUnicodeWriter_Finish`
   * ``_PyUnicodeWriter_Init()``: use :c:func:`PyUnicodeWriter_Create`
diff --git a/Include/cpython/lock.h b/Include/cpython/lock.h
index 8ee03e82f74dfd..63886fca28eae2 100644
--- a/Include/cpython/lock.h
+++ b/Include/cpython/lock.h
@@ -36,6 +36,9 @@ PyAPI_FUNC(void) PyMutex_Lock(PyMutex *m);
 // exported function for unlocking the mutex
 PyAPI_FUNC(void) PyMutex_Unlock(PyMutex *m);
 
+// exported function for checking if the mutex is locked
+PyAPI_FUNC(int) PyMutex_IsLocked(PyMutex *m);
+
 // Locks the mutex.
 //
 // If the mutex is currently locked, the calling thread will be parked until
@@ -61,3 +64,11 @@ _PyMutex_Unlock(PyMutex *m)
     }
 }
 #define PyMutex_Unlock _PyMutex_Unlock
+
+// Checks if the mutex is currently locked.
+static inline int
+_PyMutex_IsLocked(PyMutex *m)
+{
+    return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
+}
+#define PyMutex_IsLocked _PyMutex_IsLocked
diff --git a/Include/internal/pycore_lock.h b/Include/internal/pycore_lock.h
index 7484b05d7f2446..9b071573ad3c74 100644
--- a/Include/internal/pycore_lock.h
+++ b/Include/internal/pycore_lock.h
@@ -25,13 +25,6 @@ PyMutex_LockFast(PyMutex *m)
     return _Py_atomic_compare_exchange_uint8(lock_bits, &expected, _Py_LOCKED);
 }
 
-// Checks if the mutex is currently locked.
-static inline int
-PyMutex_IsLocked(PyMutex *m)
-{
-    return (_Py_atomic_load_uint8(&m->_bits) & _Py_LOCKED) != 0;
-}
-
 // Re-initializes the mutex after a fork to the unlocked state.
 static inline void
 _PyMutex_at_fork_reinit(PyMutex *m)
diff --git 
a/Misc/NEWS.d/next/C_API/2025-05-20-17-13-51.gh-issue-134009.CpCmry.rst 
b/Misc/NEWS.d/next/C_API/2025-05-20-17-13-51.gh-issue-134009.CpCmry.rst
new file mode 100644
index 00000000000000..f060f09de19bb8
--- /dev/null
+++ b/Misc/NEWS.d/next/C_API/2025-05-20-17-13-51.gh-issue-134009.CpCmry.rst
@@ -0,0 +1 @@
+Expose :c:func:`PyMutex_IsLocked` as part of the public C API.
diff --git a/Python/lock.c b/Python/lock.c
index 3c0804c468e08d..ca269bd2cb4b51 100644
--- a/Python/lock.c
+++ b/Python/lock.c
@@ -619,3 +619,11 @@ PyMutex_Unlock(PyMutex *m)
         Py_FatalError("unlocking mutex that is not locked");
     }
 }
+
+
+#undef PyMutex_IsLocked
+int
+PyMutex_IsLocked(PyMutex *m)
+{
+    return _PyMutex_IsLocked(m);
+}

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to