@@ -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+
18661894static int
18671895element_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