]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-117721: use PyMutex in `_thread.lock` (#125110) (#125116)
authorKumar Aditya <kumaraditya@python.org>
Tue, 8 Oct 2024 15:46:48 +0000 (21:16 +0530)
committerGitHub <noreply@github.com>
Tue, 8 Oct 2024 15:46:48 +0000 (21:16 +0530)
* gh-117721: use PyMutex in `_thread.lock` (#125110)

(cherry picked from commit fca552993da32044165223eec2297b6aaaac60ad)

Modules/_threadmodule.c

index b3ed8e7bc56b9eaa3121e1e4e4f0199d7122edd8..6183d0608b92b68ddb4c171e5eba868206f6e58e 100644 (file)
@@ -701,9 +701,7 @@ static PyType_Spec ThreadHandle_Type_spec = {
 
 typedef struct {
     PyObject_HEAD
-    PyThread_type_lock lock_lock;
-    PyObject *in_weakreflist;
-    char locked; /* for sanity checking */
+    PyMutex lock;
 } lockobject;
 
 static int
@@ -717,15 +715,7 @@ static void
 lock_dealloc(lockobject *self)
 {
     PyObject_GC_UnTrack(self);
-    if (self->in_weakreflist != NULL) {
-        PyObject_ClearWeakRefs((PyObject *) self);
-    }
-    if (self->lock_lock != NULL) {
-        /* Unlock the lock so it's safe to free it */
-        if (self->locked)
-            PyThread_release_lock(self->lock_lock);
-        PyThread_free_lock(self->lock_lock);
-    }
+    PyObject_ClearWeakRefs((PyObject *) self);
     PyTypeObject *tp = Py_TYPE(self);
     tp->tp_free((PyObject*)self);
     Py_DECREF(tp);
@@ -790,13 +780,12 @@ lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
     if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
         return NULL;
 
-    PyLockStatus r = acquire_timed(self->lock_lock, timeout);
+    PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout,
+                                        _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
     if (r == PY_LOCK_INTR) {
         return NULL;
     }
 
-    if (r == PY_LOCK_ACQUIRED)
-        self->locked = 1;
     return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
 }
 
@@ -827,13 +816,11 @@ static PyObject *
 lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
 {
     /* Sanity check: the lock must be locked */
-    if (!self->locked) {
+    if (_PyMutex_TryUnlock(&self->lock) < 0) {
         PyErr_SetString(ThreadError, "release unlocked lock");
         return NULL;
     }
 
-    self->locked = 0;
-    PyThread_release_lock(self->lock_lock);
     Py_RETURN_NONE;
 }
 
@@ -860,7 +847,7 @@ Release the lock.");
 static PyObject *
 lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
 {
-    return PyBool_FromLong((long)self->locked);
+    return PyBool_FromLong(PyMutex_IsLocked(&self->lock));
 }
 
 PyDoc_STRVAR(locked_doc,
@@ -879,20 +866,14 @@ static PyObject *
 lock_repr(lockobject *self)
 {
     return PyUnicode_FromFormat("<%s %s object at %p>",
-        self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
+        PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
 }
 
 #ifdef HAVE_FORK
 static PyObject *
 lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
 {
-    if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
-        PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
-        return NULL;
-    }
-
-    self->locked = 0;
-
+    _PyMutex_at_fork_reinit(&self->lock);
     Py_RETURN_NONE;
 }
 #endif  /* HAVE_FORK */
@@ -958,18 +939,12 @@ A lock is not owned by the thread that locked it; another thread may\n\
 unlock it.  A thread attempting to lock a lock that it has already locked\n\
 will block until another thread unlocks it.  Deadlocks may ensue.");
 
-static PyMemberDef lock_type_members[] = {
-    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(lockobject, in_weakreflist), Py_READONLY},
-    {NULL},
-};
-
 static PyType_Slot lock_type_slots[] = {
     {Py_tp_dealloc, (destructor)lock_dealloc},
     {Py_tp_repr, (reprfunc)lock_repr},
     {Py_tp_doc, (void *)lock_doc},
     {Py_tp_methods, lock_methods},
     {Py_tp_traverse, lock_traverse},
-    {Py_tp_members, lock_type_members},
     {Py_tp_new, lock_new},
     {0, 0}
 };
@@ -978,7 +953,7 @@ static PyType_Spec lock_type_spec = {
     .name = "_thread.lock",
     .basicsize = sizeof(lockobject),
     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-              Py_TPFLAGS_IMMUTABLETYPE),
+              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
     .slots = lock_type_slots,
 };
 
@@ -1320,16 +1295,7 @@ newlockobject(PyObject *module)
     if (self == NULL) {
         return NULL;
     }
-
-    self->lock_lock = PyThread_allocate_lock();
-    self->locked = 0;
-    self->in_weakreflist = NULL;
-
-    if (self->lock_lock == NULL) {
-        Py_DECREF(self);
-        PyErr_SetString(ThreadError, "can't allocate lock");
-        return NULL;
-    }
+    self->lock = (PyMutex){0};
     return self;
 }