diff options
author | Donghee Na <donghee.na@python.org> | 2024-03-01 23:30:35 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-01 23:30:35 (GMT) |
commit | fb5e0344e41788988171f31c6b8d4fd1a13b9041 (patch) | |
tree | 46e550b8134381869a5f44e4b651e98fe92de9c2 /Objects | |
parent | 90a1e9880fb0c03a82df6eaa9c7430b03e86531c (diff) | |
download | cpython-fb5e0344e41788988171f31c6b8d4fd1a13b9041.zip cpython-fb5e0344e41788988171f31c6b8d4fd1a13b9041.tar.gz cpython-fb5e0344e41788988171f31c6b8d4fd1a13b9041.tar.bz2 |
gh-112087: Use QSBR technique for list_new/clear for free-thread build (gh-115875)
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/listobject.c | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index 2bb7d4e..87effb1 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -502,7 +502,16 @@ list_item(PyObject *aa, Py_ssize_t i) PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); return NULL; } - return Py_NewRef(a->ob_item[i]); + PyObject *item; + Py_BEGIN_CRITICAL_SECTION(a); +#ifdef Py_GIL_DISABLED + if (!_Py_IsOwnedByCurrentThread((PyObject *)a) && !_PyObject_GC_IS_SHARED(a)) { + _PyObject_GC_SET_SHARED(a); + } +#endif + item = Py_NewRef(a->ob_item[i]); + Py_END_CRITICAL_SECTION(); + return item; } static PyObject * @@ -658,7 +667,7 @@ list_repeat(PyObject *aa, Py_ssize_t n) } static void -list_clear(PyListObject *a) +list_clear_impl(PyListObject *a, bool is_resize) { PyObject **items = a->ob_item; if (items == NULL) { @@ -674,17 +683,31 @@ list_clear(PyListObject *a) while (--i >= 0) { Py_XDECREF(items[i]); } - // TODO: Use QSBR technique, if the list is shared between threads, - PyMem_Free(items); - +#ifdef Py_GIL_DISABLED + bool use_qsbr = is_resize && _PyObject_GC_IS_SHARED(a); +#else + bool use_qsbr = false; +#endif + if (use_qsbr) { + _PyMem_FreeDelayed(items); + } + else { + PyMem_Free(items); + } // Note that there is no guarantee that the list is actually empty // at this point, because XDECREF may have populated it indirectly again! } +static void +list_clear(PyListObject *a) +{ + list_clear_impl(a, true); +} + static int list_clear_slot(PyObject *self) { - list_clear((PyListObject *)self); + list_clear_impl((PyListObject *)self, false); return 0; } |