summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorDonghee Na <donghee.na@python.org>2024-03-01 23:30:35 (GMT)
committerGitHub <noreply@github.com>2024-03-01 23:30:35 (GMT)
commitfb5e0344e41788988171f31c6b8d4fd1a13b9041 (patch)
tree46e550b8134381869a5f44e4b651e98fe92de9c2 /Objects
parent90a1e9880fb0c03a82df6eaa9c7430b03e86531c (diff)
downloadcpython-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.c35
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;
}