diff options
author | Sam Gross <colesbury@gmail.com> | 2024-06-21 20:20:41 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-21 20:20:41 (GMT) |
commit | 4dc27bc0b76aa5985ccef2901f7a4f5d36b97995 (patch) | |
tree | 3219748fd1c47dec959096aed7457cf1fad5d43a /Objects | |
parent | e748805f2a0f783723ef02809f86cd3d8fb8bf2e (diff) | |
download | cpython-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.c | 2 | ||||
-rw-r--r-- | Objects/listobject.c | 2 | ||||
-rw-r--r-- | Objects/typeobject.c | 71 |
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; |