authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-23 13:47:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-23 13:47:44-07:00
logd210f733f80731487f8f83caf621e04506f50bb4
tree4bd9994db3bec04dd8eb9c39944189c35c53f8f5
parent6bf52b0505ad7317b5f0d6fa77b7c41318b9c73b

std.Progress: fix data race

In end(), the freelist pointer is owned so the bare store would be ok. However, there is a load in start() that can happen at the same time, if another start() and end() pair grabs that same index. I don't think this fixes #21663 actually because even if the data race corrupts the value for `next`, the cmpxchg protects the value from being stored there.

1 files changed, 3 insertions(+), 2 deletions(-)

lib/std/Progress.zig+3-2
......@@ -188,7 +188,8 @@ pub const Node = struct {
188188 var opt_free_index = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);
189189 while (opt_free_index.unwrap()) |free_index| {
190190 const freelist_ptr = freelistByIndex(free_index);
191 opt_free_index = @cmpxchgWeak(Node.OptionalIndex, freelist_head, opt_free_index, freelist_ptr.*, .seq_cst, .seq_cst) orelse {
191 const next = @atomicLoad(Node.OptionalIndex, freelist_ptr, .seq_cst);
192 opt_free_index = @cmpxchgWeak(Node.OptionalIndex, freelist_head, opt_free_index, next, .seq_cst, .seq_cst) orelse {
192193 // We won the allocation race.
193194 return init(free_index, parent, name, estimated_total_items);
194195 };
......@@ -249,7 +250,7 @@ pub const Node = struct {
249250 const freelist_head = &global_progress.node_freelist_first;
250251 var first = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);
251252 while (true) {
252 freelistByIndex(index).* = first;
253 @atomicStore(Node.OptionalIndex, freelistByIndex(index), first, .seq_cst);
253254 first = @cmpxchgWeak(Node.OptionalIndex, freelist_head, first, index.toOptional(), .seq_cst, .seq_cst) orelse break;
254255 }
255256 } else {