Skip to content

Commit 908a590

Browse files
fix more thread safety issues in list
1 parent 5989095 commit 908a590

File tree

2 files changed

+63
-5
lines changed

2 files changed

+63
-5
lines changed

Lib/test/test_free_threading/test_list.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,64 @@ def copy_back_and_forth(b, l):
9191
with threading_helper.start_threads(threads):
9292
pass
9393

94+
def test_reverse(self):
95+
def reverse_list(b, l):
96+
b.wait()
97+
for _ in range(100):
98+
l.reverse()
99+
100+
def reader_list(b, l):
101+
b.wait()
102+
for _ in range(100):
103+
for i in range(10):
104+
self.assertTrue(0 <= l[i] < 10)
105+
106+
l = list(range(10))
107+
barrier = Barrier(2)
108+
threads = [Thread(target=reverse_list, args=(barrier, l)),
109+
Thread(target=reader_list, args=(barrier, l))]
110+
with threading_helper.start_threads(threads):
111+
pass
112+
113+
def test_slice_assignment1(self):
114+
def assign_slice(b, l):
115+
b.wait()
116+
for _ in range(100):
117+
l[2:5] = [7, 8, 9]
118+
119+
def reader_list(b, l):
120+
b.wait()
121+
for _ in range(100):
122+
self.assertIn(l[2], (2, 7))
123+
self.assertIn(l[3], (3, 8))
124+
self.assertIn(l[4], (4, 9))
125+
126+
l = list(range(10))
127+
barrier = Barrier(2)
128+
threads = [Thread(target=assign_slice, args=(barrier, l)),
129+
Thread(target=reader_list, args=(barrier, l))]
130+
with threading_helper.start_threads(threads):
131+
pass
132+
133+
def test_slice_assignment2(self):
134+
def assign_slice(b, l):
135+
b.wait()
136+
for _ in range(100):
137+
l[::2] = [10, 11, 12, 13, 14]
138+
139+
def reader_list(b, l):
140+
b.wait()
141+
for _ in range(100):
142+
for i in range(0, 10, 2):
143+
self.assertIn(l[i], (i, 10 + i // 2))
144+
145+
l = list(range(10))
146+
barrier = Barrier(2)
147+
threads = [Thread(target=assign_slice, args=(barrier, l)),
148+
Thread(target=reader_list, args=(barrier, l))]
149+
with threading_helper.start_threads(threads):
150+
pass
151+
94152

95153
if __name__ == "__main__":
96154
unittest.main()

Objects/listobject.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
501501
where = n;
502502
items = self->ob_item;
503503
for (i = n; --i >= where; )
504-
FT_ATOMIC_STORE_PTR_RELAXED(items[i+1], items[i]);
504+
FT_ATOMIC_STORE_PTR_RELEASE(items[i+1], items[i]);
505505
FT_ATOMIC_STORE_PTR_RELEASE(items[where], Py_NewRef(v));
506506
return 0;
507507
}
@@ -1122,7 +1122,7 @@ list_ass_item_lock_held(PyListObject *a, Py_ssize_t i, PyObject *v)
11221122
if (v == NULL) {
11231123
Py_ssize_t size = Py_SIZE(a);
11241124
for (Py_ssize_t idx = i; idx < size - 1; idx++) {
1125-
FT_ATOMIC_STORE_PTR_RELAXED(a->ob_item[idx], a->ob_item[idx + 1]);
1125+
FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item[idx], a->ob_item[idx + 1]);
11261126
}
11271127
Py_SET_SIZE(a, size - 1);
11281128
}
@@ -1601,8 +1601,8 @@ reverse_slice(PyObject **lo, PyObject **hi)
16011601
--hi;
16021602
while (lo < hi) {
16031603
PyObject *t = *lo;
1604-
*lo = *hi;
1605-
*hi = t;
1604+
FT_ATOMIC_STORE_PTR_RELEASE(*lo, *hi);
1605+
FT_ATOMIC_STORE_PTR_RELEASE(*hi, t);
16061606
++lo;
16071607
--hi;
16081608
}
@@ -3845,7 +3845,7 @@ list_ass_subscript_lock_held(PyObject *_self, PyObject *item, PyObject *value)
38453845
cur += (size_t)step, i++) {
38463846
garbage[i] = selfitems[cur];
38473847
ins = Py_NewRef(seqitems[i]);
3848-
selfitems[cur] = ins;
3848+
FT_ATOMIC_STORE_PTR_RELEASE(selfitems[cur], ins);
38493849
}
38503850

38513851
for (i = 0; i < slicelength; i++) {

0 commit comments

Comments
 (0)