-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Open
Labels
backend-llvmThe LLVM backend outputs an LLVM IR Module.The LLVM backend outputs an LLVM IR Module.bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviormiscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.upstreamAn issue with a third party project that Zig uses.An issue with a third party project that Zig uses.
Milestone
Description
Zig Version
0.12.0 (also newer versions)
Steps to Reproduce and Observed Behavior
I'm not 100% confident with atomics and memory orderings, but this might be a bug.
const std = @import("std");
var FLAG = std.atomic.Value(bool).init(false);
var SHARED_VALUE: usize = 0;
pub fn worker_fn() void {
while (true) {
if (!FLAG.load(.seq_cst)) continue;
std.debug.print("Shared value is: {}\n", .{SHARED_VALUE});
FLAG.store(false, .seq_cst);
}
}
pub fn main() !void {
_ = try std.Thread.spawn(.{}, worker_fn, .{});
SHARED_VALUE = 1;
magic();
SHARED_VALUE = 2;
magic();
}
pub fn magic() void {
FLAG.store(true, .seq_cst);
while (FLAG.load(.seq_cst)) {}
}When compiled with -O ReleaseSmall, it outputs:
Shared value is: 0
Shared value is: 2
If the magic() function is inlined (either manually or using inline), the problem disappears.
I also have this modified version that triggers this behavior in -O ReleaseFast as well:
Click to expand
const std = @import("std");
const MAGIC_NUM_1 = 6; // Try 5 :)
const MAGIC_NUM_2 = 7; // Try 6 :)
var FLAG = std.atomic.Value(bool).init(false);
var SHARED_VALUE: usize = 0;
pub fn worker_fn() void {
while (true) {
if (!FLAG.load(.seq_cst)) continue;
std.debug.print("Shared value is: {}\n", .{SHARED_VALUE});
FLAG.store(false, .seq_cst);
}
}
pub fn main() !void {
_ = try std.Thread.spawn(.{}, worker_fn, .{});
SHARED_VALUE = 1; // Optimized-out in ReleaseFast, if the magic values are just right.
magic();
SHARED_VALUE = 2;
magic();
}
pub fn magic() void {
for (0..MAGIC_NUM_1) |_| {
if (!FLAG.load(.seq_cst)) {
FLAG.store(true, .seq_cst);
}
}
for (0..MAGIC_NUM_2) |_| {
while (FLAG.load(.seq_cst)) {}
}
}Output:
Shared value is: 0
Shared value is: 2
Expected Behavior
Maybe
Shared value is: 1
Shared value is: 2
but I'm not sure.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
backend-llvmThe LLVM backend outputs an LLVM IR Module.The LLVM backend outputs an LLVM IR Module.bugObserved behavior contradicts documented or intended behaviorObserved behavior contradicts documented or intended behaviormiscompilationThe compiler reports success but produces semantically incorrect code.The compiler reports success but produces semantically incorrect code.upstreamAn issue with a third party project that Zig uses.An issue with a third party project that Zig uses.