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 {...@@ -188,7 +188,8 @@ pub const Node = struct {
188 var opt_free_index = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);188 var opt_free_index = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);
189 while (opt_free_index.unwrap()) |free_index| {189 while (opt_free_index.unwrap()) |free_index| {
190 const freelist_ptr = freelistByIndex(free_index);190 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 {
192 // We won the allocation race.193 // We won the allocation race.
193 return init(free_index, parent, name, estimated_total_items);194 return init(free_index, parent, name, estimated_total_items);
194 };195 };
...@@ -249,7 +250,7 @@ pub const Node = struct {...@@ -249,7 +250,7 @@ pub const Node = struct {
249 const freelist_head = &global_progress.node_freelist_first;250 const freelist_head = &global_progress.node_freelist_first;
250 var first = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);251 var first = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst);
251 while (true) {252 while (true) {
252 freelistByIndex(index).* = first;253 @atomicStore(Node.OptionalIndex, freelistByIndex(index), first, .seq_cst);
253 first = @cmpxchgWeak(Node.OptionalIndex, freelist_head, first, index.toOptional(), .seq_cst, .seq_cst) orelse break;254 first = @cmpxchgWeak(Node.OptionalIndex, freelist_head, first, index.toOptional(), .seq_cst, .seq_cst) orelse break;
254 }255 }
255 } else {256 } else {