zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit d210f733f80731487f8f83caf621e04506f50bb4 (tree)
parent 6bf52b0505ad7317b5f0d6fa77b7c41318b9c73b
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Wed, 23 Oct 2024 13:47:44 -0700

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.

Diffstat:
Mlib/std/Progress.zig | 5+++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig @@ -188,7 +188,8 @@ pub const Node = struct { var opt_free_index = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst); while (opt_free_index.unwrap()) |free_index| { const freelist_ptr = freelistByIndex(free_index); - opt_free_index = @cmpxchgWeak(Node.OptionalIndex, freelist_head, opt_free_index, freelist_ptr.*, .seq_cst, .seq_cst) orelse { + const next = @atomicLoad(Node.OptionalIndex, freelist_ptr, .seq_cst); + opt_free_index = @cmpxchgWeak(Node.OptionalIndex, freelist_head, opt_free_index, next, .seq_cst, .seq_cst) orelse { // We won the allocation race. return init(free_index, parent, name, estimated_total_items); }; @@ -249,7 +250,7 @@ pub const Node = struct { const freelist_head = &global_progress.node_freelist_first; var first = @atomicLoad(Node.OptionalIndex, freelist_head, .seq_cst); while (true) { - freelistByIndex(index).* = first; + @atomicStore(Node.OptionalIndex, freelistByIndex(index), first, .seq_cst); first = @cmpxchgWeak(Node.OptionalIndex, freelist_head, first, index.toOptional(), .seq_cst, .seq_cst) orelse break; } } else {