| ... | ... | @@ -2,7 +2,7 @@ const std = @import("../std.zig"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | 4 | const testing = std.testing; |
| 5 | | const Ordering = std.atomic.Ordering; |
| 5 | const AtomicOrder = std.builtin.AtomicOrder; |
| 6 | 6 | |
| 7 | 7 | pub fn Atomic(comptime T: type) type { |
| 8 | 8 | return extern struct { |
| ... | ... | @@ -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 | 42 | // LLVM's ThreadSanitizer doesn't support the normal fences so we specialize for it. |
| 43 | 43 | if (builtin.sanitize_thread) { |
| 44 | 44 | const tsan = struct { |
| ... | ... | @@ -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 | 71 | /// Non-atomically load from the atomic value without synchronization. |
| ... | ... | @@ -73,23 +80,23 @@ pub fn Atomic(comptime T: type) type { |
| 73 | 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 | 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 | 86 | .Release => @compileError(@tagName(ordering) ++ " is only allowed on atomic stores"), |
| 80 | 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 | 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 | 94 | .Acquire => @compileError(@tagName(ordering) ++ " is only allowed on atomic loads"), |
| 88 | 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 | 100 | return self.rmw(.Xchg, value, ordering); |
| 94 | 101 | } |
| 95 | 102 | |
| ... | ... | @@ -97,8 +104,8 @@ pub fn Atomic(comptime T: type) type { |
| 97 | 104 | self: *Self, |
| 98 | 105 | compare: T, |
| 99 | 106 | exchange: T, |
| 100 | | comptime success: Ordering, |
| 101 | | comptime failure: Ordering, |
| 107 | comptime success: AtomicOrder, |
| 108 | comptime failure: AtomicOrder, |
| 102 | 109 | ) ?T { |
| 103 | 110 | return self.cmpxchg(true, compare, exchange, success, failure); |
| 104 | 111 | } |
| ... | ... | @@ -107,8 +114,8 @@ pub fn Atomic(comptime T: type) type { |
| 107 | 114 | self: *Self, |
| 108 | 115 | compare: T, |
| 109 | 116 | exchange: T, |
| 110 | | comptime success: Ordering, |
| 111 | | comptime failure: Ordering, |
| 117 | comptime success: AtomicOrder, |
| 118 | comptime failure: AtomicOrder, |
| 112 | 119 | ) ?T { |
| 113 | 120 | return self.cmpxchg(false, compare, exchange, success, failure); |
| 114 | 121 | } |
| ... | ... | @@ -118,16 +125,16 @@ pub fn Atomic(comptime T: type) type { |
| 118 | 125 | comptime is_strong: bool, |
| 119 | 126 | compare: T, |
| 120 | 127 | exchange: T, |
| 121 | | comptime success: Ordering, |
| 122 | | comptime failure: Ordering, |
| 128 | comptime success: AtomicOrder, |
| 129 | comptime failure: AtomicOrder, |
| 123 | 130 | ) ?T { |
| 124 | 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 | 135 | const success_is_stronger = switch (failure) { |
| 129 | 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 | 138 | .Acquire => success == .SeqCst or success == .AcqRel or success == .Acquire, |
| 132 | 139 | .Release => @compileError(@tagName(failure) ++ " is only allowed on success"), |
| 133 | 140 | .Monotonic => true, |
| ... | ... | @@ -148,40 +155,40 @@ pub fn Atomic(comptime T: type) type { |
| 148 | 155 | self: *Self, |
| 149 | 156 | comptime op: std.builtin.AtomicRmwOp, |
| 150 | 157 | value: T, |
| 151 | | comptime ordering: Ordering, |
| 158 | comptime ordering: AtomicOrder, |
| 152 | 159 | ) T { |
| 153 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 192 | return self.rmw(.Xor, value, ordering); |
| 186 | 193 | } |
| 187 | 194 | |
| ... | ... | @@ -192,19 +199,19 @@ pub fn Atomic(comptime T: type) type { |
| 192 | 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 | 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 | 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 | 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 | 215 | // x86 supports dedicated bitwise instructions |
| 209 | 216 | if (comptime builtin.target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) { |
| 210 | 217 | // TODO: this causes std lib test failures when enabled |
| ... | ... | @@ -223,7 +230,7 @@ pub fn Atomic(comptime T: type) type { |
| 223 | 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 | 234 | const old_bit: u8 = switch (@sizeOf(T)) { |
| 228 | 235 | 2 => switch (op) { |
| 229 | 236 | .Set => asm volatile ("lock btsw %[bit], %[ptr]" |
| ... | ... | @@ -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 | 315 | fn atomicIntTypes() []const type { |
| 316 | 316 | comptime var bytes = 1; |
| 317 | 317 | comptime var types: []const type = &[_]type{}; |
| ... | ... | @@ -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 | 361 | .Monotonic, |
| 362 | 362 | .Acquire, |
| 363 | 363 | .Release, |
| ... | ... | @@ -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 | 393 | .{ .Monotonic, .Monotonic }, |
| 394 | 394 | .{ .Acquire, .Monotonic }, |
| 395 | 395 | .{ .Acquire, .Acquire }, |