_Py_atomic_load_ptr_relaxed(const void *obj)
{ return (void *)__atomic_load_n((const void **)obj, __ATOMIC_RELAXED); }
+static inline unsigned long long
+_Py_atomic_load_ullong_relaxed(const unsigned long long *obj)
+{ return __atomic_load_n(obj, __ATOMIC_RELAXED); }
+
// --- _Py_atomic_store ------------------------------------------------------
_Py_atomic_store_ssize_relaxed(Py_ssize_t *obj, Py_ssize_t value)
{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); }
+static inline void
+_Py_atomic_store_ullong_relaxed(unsigned long long *obj,
+ unsigned long long value)
+{ __atomic_store_n(obj, value, __ATOMIC_RELAXED); }
+
// --- _Py_atomic_load_ptr_acquire / _Py_atomic_store_ptr_release ------------
#include "pycore_sysmodule.h" // _PySys_GetAttr()
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
+#include <stdbool.h>
#include <stddef.h> // offsetof()
#ifdef HAVE_SIGNAL_H
# include <signal.h> // SIGINT
Py_DECREF(tp);
}
+static bool
+rlock_is_owned_by(rlockobject *self, PyThread_ident_t tid)
+{
+ PyThread_ident_t owner_tid =
+ _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
+ return owner_tid == tid && self->rlock_count > 0;
+}
+
static PyObject *
rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
{
return NULL;
tid = PyThread_get_thread_ident_ex();
- if (self->rlock_count > 0 && tid == self->rlock_owner) {
+ if (rlock_is_owned_by(self, tid)) {
unsigned long count = self->rlock_count + 1;
if (count <= self->rlock_count) {
PyErr_SetString(PyExc_OverflowError,
r = acquire_timed(self->rlock_lock, timeout);
if (r == PY_LOCK_ACQUIRED) {
assert(self->rlock_count == 0);
- self->rlock_owner = tid;
+ _Py_atomic_store_ullong_relaxed(&self->rlock_owner, tid);
self->rlock_count = 1;
}
else if (r == PY_LOCK_INTR) {
{
PyThread_ident_t tid = PyThread_get_thread_ident_ex();
- if (self->rlock_count == 0 || self->rlock_owner != tid) {
+ if (!rlock_is_owned_by(self, tid)) {
PyErr_SetString(PyExc_RuntimeError,
"cannot release un-acquired lock");
return NULL;
}
if (--self->rlock_count == 0) {
- self->rlock_owner = 0;
+ _Py_atomic_store_ullong_relaxed(&self->rlock_owner, 0);
PyThread_release_lock(self->rlock_lock);
}
Py_RETURN_NONE;
return NULL;
}
assert(self->rlock_count == 0);
- self->rlock_owner = owner;
+ _Py_atomic_store_ullong_relaxed(&self->rlock_owner, owner);
self->rlock_count = count;
Py_RETURN_NONE;
}
owner = self->rlock_owner;
count = self->rlock_count;
self->rlock_count = 0;
- self->rlock_owner = 0;
+ _Py_atomic_store_ullong_relaxed(&self->rlock_owner, 0);
PyThread_release_lock(self->rlock_lock);
return Py_BuildValue("k" Py_PARSE_THREAD_IDENT_T, count, owner);
}
rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored))
{
PyThread_ident_t tid = PyThread_get_thread_ident_ex();
- return PyLong_FromUnsignedLong(
- self->rlock_owner == tid ? self->rlock_count : 0UL);
+ PyThread_ident_t owner =
+ _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
+ return PyLong_FromUnsignedLong(owner == tid ? self->rlock_count : 0UL);
}
PyDoc_STRVAR(rlock_recursion_count_doc,
{
PyThread_ident_t tid = PyThread_get_thread_ident_ex();
- if (self->rlock_count > 0 && self->rlock_owner == tid) {
+ if (rlock_is_owned_by(self, tid)) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
static PyObject *
rlock_repr(rlockobject *self)
{
+ PyThread_ident_t owner =
+ _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
return PyUnicode_FromFormat(
"<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%lu at %p>",
self->rlock_count ? "locked" : "unlocked",
- Py_TYPE(self)->tp_name, self->rlock_owner,
+ Py_TYPE(self)->tp_name, owner,
self->rlock_count, self);
}