Skip to content

Commit bd716e0

Browse files
kumaraditya303efimov-mikhail
authored andcommitted
pythongh-117721: use PyMutex in _thread.lock (python#125110)
1 parent 8eec02d commit bd716e0

File tree

1 file changed

+11
-45
lines changed

1 file changed

+11
-45
lines changed

Modules/_threadmodule.c

+11-45
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,7 @@ static PyType_Spec ThreadHandle_Type_spec = {
705705

706706
typedef struct {
707707
PyObject_HEAD
708-
PyThread_type_lock lock_lock;
709-
PyObject *in_weakreflist;
710-
char locked; /* for sanity checking */
708+
PyMutex lock;
711709
} lockobject;
712710

713711
static int
@@ -722,15 +720,7 @@ lock_dealloc(PyObject *op)
722720
{
723721
lockobject *self = (lockobject*)op;
724722
PyObject_GC_UnTrack(self);
725-
if (self->in_weakreflist != NULL) {
726-
PyObject_ClearWeakRefs((PyObject *) self);
727-
}
728-
if (self->lock_lock != NULL) {
729-
/* Unlock the lock so it's safe to free it */
730-
if (self->locked)
731-
PyThread_release_lock(self->lock_lock);
732-
PyThread_free_lock(self->lock_lock);
733-
}
723+
PyObject_ClearWeakRefs((PyObject *) self);
734724
PyTypeObject *tp = Py_TYPE(self);
735725
tp->tp_free((PyObject*)self);
736726
Py_DECREF(tp);
@@ -798,13 +788,12 @@ lock_PyThread_acquire_lock(PyObject *op, PyObject *args, PyObject *kwds)
798788
return NULL;
799789
}
800790

801-
PyLockStatus r = acquire_timed(self->lock_lock, timeout);
791+
PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout,
792+
_PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
802793
if (r == PY_LOCK_INTR) {
803794
return NULL;
804795
}
805796

806-
if (r == PY_LOCK_ACQUIRED)
807-
self->locked = 1;
808797
return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
809798
}
810799

@@ -836,13 +825,11 @@ lock_PyThread_release_lock(PyObject *op, PyObject *Py_UNUSED(ignored))
836825
{
837826
lockobject *self = (lockobject*)op;
838827
/* Sanity check: the lock must be locked */
839-
if (!self->locked) {
828+
if (_PyMutex_TryUnlock(&self->lock) < 0) {
840829
PyErr_SetString(ThreadError, "release unlocked lock");
841830
return NULL;
842831
}
843832

844-
self->locked = 0;
845-
PyThread_release_lock(self->lock_lock);
846833
Py_RETURN_NONE;
847834
}
848835

@@ -870,7 +857,7 @@ static PyObject *
870857
lock_locked_lock(PyObject *op, PyObject *Py_UNUSED(ignored))
871858
{
872859
lockobject *self = (lockobject*)op;
873-
return PyBool_FromLong((long)self->locked);
860+
return PyBool_FromLong(PyMutex_IsLocked(&self->lock));
874861
}
875862

876863
PyDoc_STRVAR(locked_doc,
@@ -890,21 +877,15 @@ lock_repr(PyObject *op)
890877
{
891878
lockobject *self = (lockobject*)op;
892879
return PyUnicode_FromFormat("<%s %s object at %p>",
893-
self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
880+
PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
894881
}
895882

896883
#ifdef HAVE_FORK
897884
static PyObject *
898885
lock__at_fork_reinit(PyObject *op, PyObject *Py_UNUSED(args))
899886
{
900-
lockobject *self = (lockobject*)op;
901-
if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
902-
PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
903-
return NULL;
904-
}
905-
906-
self->locked = 0;
907-
887+
lockobject *self = (lockobject *)op;
888+
_PyMutex_at_fork_reinit(&self->lock);
908889
Py_RETURN_NONE;
909890
}
910891
#endif /* HAVE_FORK */
@@ -970,18 +951,12 @@ A lock is not owned by the thread that locked it; another thread may\n\
970951
unlock it. A thread attempting to lock a lock that it has already locked\n\
971952
will block until another thread unlocks it. Deadlocks may ensue.");
972953

973-
static PyMemberDef lock_type_members[] = {
974-
{"__weaklistoffset__", Py_T_PYSSIZET, offsetof(lockobject, in_weakreflist), Py_READONLY},
975-
{NULL},
976-
};
977-
978954
static PyType_Slot lock_type_slots[] = {
979955
{Py_tp_dealloc, lock_dealloc},
980956
{Py_tp_repr, lock_repr},
981957
{Py_tp_doc, (void *)lock_doc},
982958
{Py_tp_methods, lock_methods},
983959
{Py_tp_traverse, lock_traverse},
984-
{Py_tp_members, lock_type_members},
985960
{Py_tp_new, lock_new},
986961
{0, 0}
987962
};
@@ -990,7 +965,7 @@ static PyType_Spec lock_type_spec = {
990965
.name = "_thread.lock",
991966
.basicsize = sizeof(lockobject),
992967
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
993-
Py_TPFLAGS_IMMUTABLETYPE),
968+
Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
994969
.slots = lock_type_slots,
995970
};
996971

@@ -1340,16 +1315,7 @@ newlockobject(PyObject *module)
13401315
if (self == NULL) {
13411316
return NULL;
13421317
}
1343-
1344-
self->lock_lock = PyThread_allocate_lock();
1345-
self->locked = 0;
1346-
self->in_weakreflist = NULL;
1347-
1348-
if (self->lock_lock == NULL) {
1349-
Py_DECREF(self);
1350-
PyErr_SetString(ThreadError, "can't allocate lock");
1351-
return NULL;
1352-
}
1318+
self->lock = (PyMutex){0};
13531319
return self;
13541320
}
13551321

0 commit comments

Comments
 (0)