summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-06-21 20:20:41 (GMT)
committerGitHub <noreply@github.com>2024-06-21 20:20:41 (GMT)
commit4dc27bc0b76aa5985ccef2901f7a4f5d36b97995 (patch)
tree3219748fd1c47dec959096aed7457cf1fad5d43a /Objects
parente748805f2a0f783723ef02809f86cd3d8fb8bf2e (diff)
downloadcpython-4dc27bc0b76aa5985ccef2901f7a4f5d36b97995.zip
cpython-4dc27bc0b76aa5985ccef2901f7a4f5d36b97995.tar.gz
cpython-4dc27bc0b76aa5985ccef2901f7a4f5d36b97995.tar.bz2
[3.13] gh-119344: Make critical section API public (GH-119353) (#120856)
This makes the following macros public as part of the non-limited C-API for locking a single object or two objects at once. * `Py_BEGIN_CRITICAL_SECTION(op)` / `Py_END_CRITICAL_SECTION()` * `Py_BEGIN_CRITICAL_SECTION2(a, b)` / `Py_END_CRITICAL_SECTION2()` The supporting functions and structs used by the macros are also exposed for cases where C macros are not available. (cherry picked from commit 8f17d69b7bc906e8407095317842cc0fd52cd84a)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/dictobject.c2
-rw-r--r--Objects/listobject.c2
-rw-r--r--Objects/typeobject.c71
3 files changed, 32 insertions, 43 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 6e1c3b9..c7ea6bf 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -3109,7 +3109,7 @@ _PyDict_FromKeys(PyObject *cls, PyObject *iterable, PyObject *value)
goto dict_iter_exit;
}
}
-dict_iter_exit:
+dict_iter_exit:;
Py_END_CRITICAL_SECTION();
} else {
while ((key = PyIter_Next(it)) != NULL) {
diff --git a/Objects/listobject.c b/Objects/listobject.c
index a05ddea..dc9df3c 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -452,7 +452,7 @@ PyList_SetItem(PyObject *op, Py_ssize_t i,
p = self->ob_item + i;
Py_XSETREF(*p, newitem);
ret = 0;
-end:
+end:;
Py_END_CRITICAL_SECTION();
return ret;
}
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 7c11d87..79085b6 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -62,24 +62,13 @@ class object "PyObject *" "&PyBaseObject_Type"
// be released and reacquired during a subclass update if there's contention
// on the subclass lock.
#define TYPE_LOCK &PyInterpreterState_Get()->types.mutex
-#define BEGIN_TYPE_LOCK() \
- { \
- _PyCriticalSection _cs; \
- _PyCriticalSection_Begin(&_cs, TYPE_LOCK); \
+#define BEGIN_TYPE_LOCK() Py_BEGIN_CRITICAL_SECTION_MUT(TYPE_LOCK)
+#define END_TYPE_LOCK() Py_END_CRITICAL_SECTION()
-#define END_TYPE_LOCK() \
- _PyCriticalSection_End(&_cs); \
- }
-
-#define BEGIN_TYPE_DICT_LOCK(d) \
- { \
- _PyCriticalSection2 _cs; \
- _PyCriticalSection2_Begin(&_cs, TYPE_LOCK, \
- &_PyObject_CAST(d)->ob_mutex); \
+#define BEGIN_TYPE_DICT_LOCK(d) \
+ Py_BEGIN_CRITICAL_SECTION2_MUT(TYPE_LOCK, &_PyObject_CAST(d)->ob_mutex)
-#define END_TYPE_DICT_LOCK() \
- _PyCriticalSection2_End(&_cs); \
- }
+#define END_TYPE_DICT_LOCK() Py_END_CRITICAL_SECTION2()
#define ASSERT_TYPE_LOCK_HELD() \
_Py_CRITICAL_SECTION_ASSERT_MUTEX_LOCKED(TYPE_LOCK)
@@ -442,7 +431,7 @@ _PyType_GetBases(PyTypeObject *self)
BEGIN_TYPE_LOCK();
res = lookup_tp_bases(self);
Py_INCREF(res);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return res;
}
@@ -513,7 +502,7 @@ _PyType_GetMRO(PyTypeObject *self)
BEGIN_TYPE_LOCK();
mro = lookup_tp_mro(self);
Py_XINCREF(mro);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return mro;
#else
return Py_XNewRef(lookup_tp_mro(self));
@@ -950,10 +939,10 @@ PyType_Watch(int watcher_id, PyObject* obj)
return -1;
}
// ensure we will get a callback on the next modification
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
assign_version_tag(interp, type);
type->tp_watched |= (1 << watcher_id);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return 0;
}
@@ -1063,9 +1052,9 @@ PyType_Modified(PyTypeObject *type)
return;
}
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
type_modified_unlocked(type);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
}
static int
@@ -1185,9 +1174,9 @@ int PyUnstable_Type_AssignVersionTag(PyTypeObject *type)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
int assigned;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
assigned = assign_version_tag(interp, type);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return assigned;
}
@@ -1470,7 +1459,7 @@ type_get_mro(PyTypeObject *type, void *context)
{
PyObject *mro;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
mro = lookup_tp_mro(type);
if (mro == NULL) {
mro = Py_None;
@@ -1478,7 +1467,7 @@ type_get_mro(PyTypeObject *type, void *context)
Py_INCREF(mro);
}
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return mro;
}
@@ -2924,9 +2913,9 @@ static PyObject *
mro_implementation(PyTypeObject *type)
{
PyObject *mro;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
mro = mro_implementation_unlocked(type);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return mro;
}
@@ -3113,9 +3102,9 @@ static int
mro_internal(PyTypeObject *type, PyObject **p_old_mro)
{
int res;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
res = mro_internal_unlocked(type, 0, p_old_mro);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return res;
}
@@ -4980,7 +4969,7 @@ get_module_by_def(PyTypeObject *type, PyModuleDef *def)
}
PyObject *res = NULL;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
PyObject *mro = lookup_tp_mro(type);
// The type must be ready
@@ -5007,7 +4996,7 @@ get_module_by_def(PyTypeObject *type, PyModuleDef *def)
break;
}
}
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return res;
}
@@ -5265,13 +5254,13 @@ _PyType_LookupRef(PyTypeObject *type, PyObject *name)
int has_version = 0;
int version = 0;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
res = find_name_in_mro(type, name, &error);
if (MCACHE_CACHEABLE_NAME(name)) {
has_version = assign_version_tag(interp, type);
version = type->tp_version_tag;
}
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
/* Only put NULL results into cache if there was no error. */
if (error) {
@@ -8262,14 +8251,14 @@ PyType_Ready(PyTypeObject *type)
}
int res;
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
if (!(type->tp_flags & Py_TPFLAGS_READY)) {
res = type_ready(type, 1);
} else {
res = 0;
assert(_PyType_CheckConsistency(type));
}
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return res;
}
@@ -8303,7 +8292,7 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
int res;
BEGIN_TYPE_LOCK();
res = type_ready(self, initial);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
if (res < 0) {
_PyStaticType_ClearWeakRefs(interp, self);
managed_static_type_state_clear(interp, self, isbuiltin, initial);
@@ -8775,7 +8764,7 @@ hackcheck(PyObject *self, setattrofunc func, const char *what)
int res;
BEGIN_TYPE_LOCK();
res = hackcheck_unlocked(self, func, what);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
return res;
}
@@ -10704,14 +10693,14 @@ fixup_slot_dispatchers(PyTypeObject *type)
// This lock isn't strictly necessary because the type has not been
// exposed to anyone else yet, but update_ont_slot calls find_name_in_mro
// where we'd like to assert that the type is locked.
- BEGIN_TYPE_LOCK()
+ BEGIN_TYPE_LOCK();
assert(!PyErr_Occurred());
for (pytype_slotdef *p = slotdefs; p->name; ) {
p = update_one_slot(type, p);
}
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
}
static void
@@ -11000,7 +10989,7 @@ _super_lookup_descr(PyTypeObject *su_type, PyTypeObject *su_obj_type, PyObject *
another thread can modify it after we end the critical section
below */
Py_XINCREF(mro);
- END_TYPE_LOCK()
+ END_TYPE_LOCK();
if (mro == NULL)
return NULL;