Skip to content

Commit d2f1fb3

Browse files
authored
Update _elementtree.c
1 parent acefff9 commit d2f1fb3

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

Modules/_elementtree.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,6 +1863,34 @@ element_subscr(PyObject *op, PyObject *item)
18631863
}
18641864
}
18651865

1866+
// Pointer-by-pointer memmove for PyObject** arrays that is safe
1867+
// for shared ElementObjects in Py_GIL_DISABLED builds.
1868+
static void
1869+
ptr_wise_atomic_memmove(ElementObject *a, PyObject **dest, PyObject **src, Py_ssize_t n)
1870+
{
1871+
#ifndef Py_GIL_DISABLED
1872+
memmove(dest, src, n * sizeof(PyObject *));
1873+
#else
1874+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(a);
1875+
if (_Py_IsOwnedByCurrentThread((PyObject *)a) && !_PyObject_GC_IS_SHARED(a)) {
1876+
// No other threads can read this list concurrently
1877+
memmove(dest, src, n * sizeof(PyObject *));
1878+
return;
1879+
}
1880+
if (dest < src) {
1881+
for (Py_ssize_t i = 0; i != n; i++) {
1882+
_Py_atomic_store_ptr_release(&dest[i], src[i]);
1883+
}
1884+
}
1885+
else {
1886+
// copy backwards to avoid overwriting src before it's read
1887+
for (Py_ssize_t i = n; i != 0; i--) {
1888+
_Py_atomic_store_ptr_release(&dest[i - 1], src[i - 1]);
1889+
}
1890+
}
1891+
#endif
1892+
}
1893+
18661894
static int
18671895
element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
18681896
{
@@ -1938,19 +1966,21 @@ element_ass_subscr(PyObject *op, PyObject *item, PyObject *value)
19381966

19391967
PyList_SET_ITEM(recycle, i, self->extra->children[cur]);
19401968

1941-
memmove(
1969+
ptr_wise_atomic_memmove(
1970+
self,
19421971
self->extra->children + cur - i,
19431972
self->extra->children + cur + 1,
1944-
num_moved * sizeof(PyObject *));
1973+
num_moved);
19451974
}
19461975

19471976
/* Leftover "tail" after the last removed child */
19481977
cur = start + (size_t)slicelen * step;
19491978
if (cur < (size_t)self->extra->length) {
1950-
memmove(
1979+
ptr_wise_atomic_memmove(
1980+
self,
19511981
self->extra->children + cur - slicelen,
19521982
self->extra->children + cur,
1953-
(self->extra->length - cur) * sizeof(PyObject *));
1983+
self->extra->length - cur);
19541984
}
19551985

19561986
self->extra->length -= slicelen;

0 commit comments

Comments
 (0)