| ... | @@ -2,7 +2,7 @@ const std = @import("../std.zig"); | ... | @@ -2,7 +2,7 @@ const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | | 3 | |
| 4 | const testing = std.testing; | 4 | const testing = std.testing; |
| 5 | const Ordering = std.atomic.Ordering; | 5 | const AtomicOrder = std.builtin.AtomicOrder; |
| 6 | | 6 | |
| 7 | pub fn Atomic(comptime T: type) type { | 7 | pub fn Atomic(comptime T: type) type { |
| 8 | return extern struct { | 8 | return extern struct { |
| ... | @@ -38,7 +38,7 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -38,7 +38,7 @@ pub fn Atomic(comptime T: type) type { |
| 38 | /// } | 38 | /// } |
| 39 | /// }; | 39 | /// }; |
| 40 | /// ``` | 40 | /// ``` |
| 41 | pub inline fn fence(self: *Self, comptime ordering: Ordering) void { | 41 | pub inline fn fence(self: *Self, comptime ordering: AtomicOrder) void { |
| 42 | // LLVM's ThreadSanitizer doesn't support the normal fences so we specialize for it. | 42 | // LLVM's ThreadSanitizer doesn't support the normal fences so we specialize for it. |
| 43 | if (builtin.sanitize_thread) { | 43 | if (builtin.sanitize_thread) { |
| 44 | const tsan = struct { | 44 | const tsan = struct { |
| ... | @@ -58,7 +58,14 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -58,7 +58,14 @@ pub fn Atomic(comptime T: type) type { |
| 58 | }; | 58 | }; |
| 59 | } | 59 | } |
| 60 | | 60 | |
| 61 | return std.atomic.fence(ordering); | 61 | return @fence(ordering); |
| | 62 | } |
| | 63 | |
| | 64 | test fence { |
| | 65 | inline for (.{ .Acquire, .Release, .AcqRel, .SeqCst }) |ordering| { |
| | 66 | var x = Atomic(usize).init(0); |
| | 67 | x.fence(ordering); |
| | 68 | } |
| 62 | } | 69 | } |
| 63 | | 70 | |
| 64 | /// Non-atomically load from the atomic value without synchronization. | 71 | /// Non-atomically load from the atomic value without synchronization. |
| ... | @@ -73,23 +80,23 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -73,23 +80,23 @@ pub fn Atomic(comptime T: type) type { |
| 73 | self.value = value; | 80 | self.value = value; |
| 74 | } | 81 | } |
| 75 | | 82 | |
| 76 | pub inline fn load(self: *const Self, comptime ordering: Ordering) T { | 83 | pub inline fn load(self: *const Self, comptime ordering: AtomicOrder) T { |
| 77 | return switch (ordering) { | 84 | return switch (ordering) { |
| 78 | .AcqRel => @compileError(@tagName(ordering) ++ " implies " ++ @tagName(Ordering.Release) ++ " which is only allowed on atomic stores"), | 85 | .AcqRel => @compileError(@tagName(ordering) ++ " implies " ++ @tagName(AtomicOrder.Release) ++ " which is only allowed on atomic stores"), |
| 79 | .Release => @compileError(@tagName(ordering) ++ " is only allowed on atomic stores"), | 86 | .Release => @compileError(@tagName(ordering) ++ " is only allowed on atomic stores"), |
| 80 | else => @atomicLoad(T, &self.value, ordering), | 87 | else => @atomicLoad(T, &self.value, ordering), |
| 81 | }; | 88 | }; |
| 82 | } | 89 | } |
| 83 | | 90 | |
| 84 | pub inline fn store(self: *Self, value: T, comptime ordering: Ordering) void { | 91 | pub inline fn store(self: *Self, value: T, comptime ordering: AtomicOrder) void { |
| 85 | switch (ordering) { | 92 | switch (ordering) { |
| 86 | .AcqRel => @compileError(@tagName(ordering) ++ " implies " ++ @tagName(Ordering.Acquire) ++ " which is only allowed on atomic loads"), | 93 | .AcqRel => @compileError(@tagName(ordering) ++ " implies " ++ @tagName(AtomicOrder.Acquire) ++ " which is only allowed on atomic loads"), |
| 87 | .Acquire => @compileError(@tagName(ordering) ++ " is only allowed on atomic loads"), | 94 | .Acquire => @compileError(@tagName(ordering) ++ " is only allowed on atomic loads"), |
| 88 | else => @atomicStore(T, &self.value, value, ordering), | 95 | else => @atomicStore(T, &self.value, value, ordering), |
| 89 | } | 96 | } |
| 90 | } | 97 | } |
| 91 | | 98 | |
| 92 | pub inline fn swap(self: *Self, value: T, comptime ordering: Ordering) T { | 99 | pub inline fn swap(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 93 | return self.rmw(.Xchg, value, ordering); | 100 | return self.rmw(.Xchg, value, ordering); |
| 94 | } | 101 | } |
| 95 | | 102 | |
| ... | @@ -97,8 +104,8 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -97,8 +104,8 @@ pub fn Atomic(comptime T: type) type { |
| 97 | self: *Self, | 104 | self: *Self, |
| 98 | compare: T, | 105 | compare: T, |
| 99 | exchange: T, | 106 | exchange: T, |
| 100 | comptime success: Ordering, | 107 | comptime success: AtomicOrder, |
| 101 | comptime failure: Ordering, | 108 | comptime failure: AtomicOrder, |
| 102 | ) ?T { | 109 | ) ?T { |
| 103 | return self.cmpxchg(true, compare, exchange, success, failure); | 110 | return self.cmpxchg(true, compare, exchange, success, failure); |
| 104 | } | 111 | } |
| ... | @@ -107,8 +114,8 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -107,8 +114,8 @@ pub fn Atomic(comptime T: type) type { |
| 107 | self: *Self, | 114 | self: *Self, |
| 108 | compare: T, | 115 | compare: T, |
| 109 | exchange: T, | 116 | exchange: T, |
| 110 | comptime success: Ordering, | 117 | comptime success: AtomicOrder, |
| 111 | comptime failure: Ordering, | 118 | comptime failure: AtomicOrder, |
| 112 | ) ?T { | 119 | ) ?T { |
| 113 | return self.cmpxchg(false, compare, exchange, success, failure); | 120 | return self.cmpxchg(false, compare, exchange, success, failure); |
| 114 | } | 121 | } |
| ... | @@ -118,16 +125,16 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -118,16 +125,16 @@ pub fn Atomic(comptime T: type) type { |
| 118 | comptime is_strong: bool, | 125 | comptime is_strong: bool, |
| 119 | compare: T, | 126 | compare: T, |
| 120 | exchange: T, | 127 | exchange: T, |
| 121 | comptime success: Ordering, | 128 | comptime success: AtomicOrder, |
| 122 | comptime failure: Ordering, | 129 | comptime failure: AtomicOrder, |
| 123 | ) ?T { | 130 | ) ?T { |
| 124 | if (success == .Unordered or failure == .Unordered) { | 131 | if (success == .Unordered or failure == .Unordered) { |
| 125 | @compileError(@tagName(Ordering.Unordered) ++ " is only allowed on atomic loads and stores"); | 132 | @compileError(@tagName(AtomicOrder.Unordered) ++ " is only allowed on atomic loads and stores"); |
| 126 | } | 133 | } |
| 127 | | 134 | |
| 128 | const success_is_stronger = switch (failure) { | 135 | const success_is_stronger = switch (failure) { |
| 129 | .SeqCst => success == .SeqCst, | 136 | .SeqCst => success == .SeqCst, |
| 130 | .AcqRel => @compileError(@tagName(failure) ++ " implies " ++ @tagName(Ordering.Release) ++ " which is only allowed on success"), | 137 | .AcqRel => @compileError(@tagName(failure) ++ " implies " ++ @tagName(AtomicOrder.Release) ++ " which is only allowed on success"), |
| 131 | .Acquire => success == .SeqCst or success == .AcqRel or success == .Acquire, | 138 | .Acquire => success == .SeqCst or success == .AcqRel or success == .Acquire, |
| 132 | .Release => @compileError(@tagName(failure) ++ " is only allowed on success"), | 139 | .Release => @compileError(@tagName(failure) ++ " is only allowed on success"), |
| 133 | .Monotonic => true, | 140 | .Monotonic => true, |
| ... | @@ -148,40 +155,40 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -148,40 +155,40 @@ pub fn Atomic(comptime T: type) type { |
| 148 | self: *Self, | 155 | self: *Self, |
| 149 | comptime op: std.builtin.AtomicRmwOp, | 156 | comptime op: std.builtin.AtomicRmwOp, |
| 150 | value: T, | 157 | value: T, |
| 151 | comptime ordering: Ordering, | 158 | comptime ordering: AtomicOrder, |
| 152 | ) T { | 159 | ) T { |
| 153 | return @atomicRmw(T, &self.value, op, value, ordering); | 160 | return @atomicRmw(T, &self.value, op, value, ordering); |
| 154 | } | 161 | } |
| 155 | | 162 | |
| 156 | pub inline fn fetchAdd(self: *Self, value: T, comptime ordering: Ordering) T { | 163 | pub inline fn fetchAdd(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 157 | return self.rmw(.Add, value, ordering); | 164 | return self.rmw(.Add, value, ordering); |
| 158 | } | 165 | } |
| 159 | | 166 | |
| 160 | pub inline fn fetchSub(self: *Self, value: T, comptime ordering: Ordering) T { | 167 | pub inline fn fetchSub(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 161 | return self.rmw(.Sub, value, ordering); | 168 | return self.rmw(.Sub, value, ordering); |
| 162 | } | 169 | } |
| 163 | | 170 | |
| 164 | pub inline fn fetchMin(self: *Self, value: T, comptime ordering: Ordering) T { | 171 | pub inline fn fetchMin(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 165 | return self.rmw(.Min, value, ordering); | 172 | return self.rmw(.Min, value, ordering); |
| 166 | } | 173 | } |
| 167 | | 174 | |
| 168 | pub inline fn fetchMax(self: *Self, value: T, comptime ordering: Ordering) T { | 175 | pub inline fn fetchMax(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 169 | return self.rmw(.Max, value, ordering); | 176 | return self.rmw(.Max, value, ordering); |
| 170 | } | 177 | } |
| 171 | | 178 | |
| 172 | pub inline fn fetchAnd(self: *Self, value: T, comptime ordering: Ordering) T { | 179 | pub inline fn fetchAnd(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 173 | return self.rmw(.And, value, ordering); | 180 | return self.rmw(.And, value, ordering); |
| 174 | } | 181 | } |
| 175 | | 182 | |
| 176 | pub inline fn fetchNand(self: *Self, value: T, comptime ordering: Ordering) T { | 183 | pub inline fn fetchNand(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 177 | return self.rmw(.Nand, value, ordering); | 184 | return self.rmw(.Nand, value, ordering); |
| 178 | } | 185 | } |
| 179 | | 186 | |
| 180 | pub inline fn fetchOr(self: *Self, value: T, comptime ordering: Ordering) T { | 187 | pub inline fn fetchOr(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 181 | return self.rmw(.Or, value, ordering); | 188 | return self.rmw(.Or, value, ordering); |
| 182 | } | 189 | } |
| 183 | | 190 | |
| 184 | pub inline fn fetchXor(self: *Self, value: T, comptime ordering: Ordering) T { | 191 | pub inline fn fetchXor(self: *Self, value: T, comptime ordering: AtomicOrder) T { |
| 185 | return self.rmw(.Xor, value, ordering); | 192 | return self.rmw(.Xor, value, ordering); |
| 186 | } | 193 | } |
| 187 | | 194 | |
| ... | @@ -192,19 +199,19 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -192,19 +199,19 @@ pub fn Atomic(comptime T: type) type { |
| 192 | Toggle, | 199 | Toggle, |
| 193 | }; | 200 | }; |
| 194 | | 201 | |
| 195 | pub inline fn bitSet(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { | 202 | pub inline fn bitSet(self: *Self, bit: Bit, comptime ordering: AtomicOrder) u1 { |
| 196 | return bitRmw(self, .Set, bit, ordering); | 203 | return bitRmw(self, .Set, bit, ordering); |
| 197 | } | 204 | } |
| 198 | | 205 | |
| 199 | pub inline fn bitReset(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { | 206 | pub inline fn bitReset(self: *Self, bit: Bit, comptime ordering: AtomicOrder) u1 { |
| 200 | return bitRmw(self, .Reset, bit, ordering); | 207 | return bitRmw(self, .Reset, bit, ordering); |
| 201 | } | 208 | } |
| 202 | | 209 | |
| 203 | pub inline fn bitToggle(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { | 210 | pub inline fn bitToggle(self: *Self, bit: Bit, comptime ordering: AtomicOrder) u1 { |
| 204 | return bitRmw(self, .Toggle, bit, ordering); | 211 | return bitRmw(self, .Toggle, bit, ordering); |
| 205 | } | 212 | } |
| 206 | | 213 | |
| 207 | inline fn bitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 { | 214 | inline fn bitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: AtomicOrder) u1 { |
| 208 | // x86 supports dedicated bitwise instructions | 215 | // x86 supports dedicated bitwise instructions |
| 209 | if (comptime builtin.target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) { | 216 | if (comptime builtin.target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) { |
| 210 | // TODO: this causes std lib test failures when enabled | 217 | // TODO: this causes std lib test failures when enabled |
| ... | @@ -223,7 +230,7 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -223,7 +230,7 @@ pub fn Atomic(comptime T: type) type { |
| 223 | return @intFromBool(value & mask != 0); | 230 | return @intFromBool(value & mask != 0); |
| 224 | } | 231 | } |
| 225 | | 232 | |
| 226 | inline fn x86BitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering) u1 { | 233 | inline fn x86BitRmw(self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: AtomicOrder) u1 { |
| 227 | const old_bit: u8 = switch (@sizeOf(T)) { | 234 | const old_bit: u8 = switch (@sizeOf(T)) { |
| 228 | 2 => switch (op) { | 235 | 2 => switch (op) { |
| 229 | .Set => asm volatile ("lock btsw %[bit], %[ptr]" | 236 | .Set => asm volatile ("lock btsw %[bit], %[ptr]" |
| ... | @@ -305,13 +312,6 @@ pub fn Atomic(comptime T: type) type { | ... | @@ -305,13 +312,6 @@ pub fn Atomic(comptime T: type) type { |
| 305 | }; | 312 | }; |
| 306 | } | 313 | } |
| 307 | | 314 | |
| 308 | test "Atomic.fence" { | | |
| 309 | inline for (.{ .Acquire, .Release, .AcqRel, .SeqCst }) |ordering| { | | |
| 310 | var x = Atomic(usize).init(0); | | |
| 311 | x.fence(ordering); | | |
| 312 | } | | |
| 313 | } | | |
| 314 | | | |
| 315 | fn atomicIntTypes() []const type { | 315 | fn atomicIntTypes() []const type { |
| 316 | comptime var bytes = 1; | 316 | comptime var bytes = 1; |
| 317 | comptime var types: []const type = &[_]type{}; | 317 | comptime var types: []const type = &[_]type{}; |
| ... | @@ -357,7 +357,7 @@ test "Atomic.store" { | ... | @@ -357,7 +357,7 @@ test "Atomic.store" { |
| 357 | } | 357 | } |
| 358 | } | 358 | } |
| 359 | | 359 | |
| 360 | const atomic_rmw_orderings = [_]Ordering{ | 360 | const atomic_rmw_orderings = [_]AtomicOrder{ |
| 361 | .Monotonic, | 361 | .Monotonic, |
| 362 | .Acquire, | 362 | .Acquire, |
| 363 | .Release, | 363 | .Release, |
| ... | @@ -389,7 +389,7 @@ test "Atomic.swap" { | ... | @@ -389,7 +389,7 @@ test "Atomic.swap" { |
| 389 | } | 389 | } |
| 390 | } | 390 | } |
| 391 | | 391 | |
| 392 | const atomic_cmpxchg_orderings = [_][2]Ordering{ | 392 | const atomic_cmpxchg_orderings = [_][2]AtomicOrder{ |
| 393 | .{ .Monotonic, .Monotonic }, | 393 | .{ .Monotonic, .Monotonic }, |
| 394 | .{ .Acquire, .Monotonic }, | 394 | .{ .Acquire, .Monotonic }, |
| 395 | .{ .Acquire, .Acquire }, | 395 | .{ .Acquire, .Acquire }, |