@@ -153,163 +153,155 @@ pub fn Atomic(comptime T: type) type {
153
153
return @atomicRmw (T , & self .value , op , value , ordering );
154
154
}
155
155
156
- fn exportWhen ( comptime condition : bool , comptime functions : type ) type {
157
- return if ( condition ) functions else struct {} ;
156
+ pub inline fn fetchAdd ( self : * Self , value : T , comptime ordering : Ordering ) T {
157
+ return self . rmw ( .Add , value , ordering ) ;
158
158
}
159
159
160
- pub usingnamespace exportWhen (std .meta .trait .isNumber (T ), struct {
161
- pub inline fn fetchAdd (self : * Self , value : T , comptime ordering : Ordering ) T {
162
- return self .rmw (.Add , value , ordering );
163
- }
164
-
165
- pub inline fn fetchSub (self : * Self , value : T , comptime ordering : Ordering ) T {
166
- return self .rmw (.Sub , value , ordering );
167
- }
160
+ pub inline fn fetchSub (self : * Self , value : T , comptime ordering : Ordering ) T {
161
+ return self .rmw (.Sub , value , ordering );
162
+ }
168
163
169
- pub inline fn fetchMin (self : * Self , value : T , comptime ordering : Ordering ) T {
170
- return self .rmw (.Min , value , ordering );
171
- }
164
+ pub inline fn fetchMin (self : * Self , value : T , comptime ordering : Ordering ) T {
165
+ return self .rmw (.Min , value , ordering );
166
+ }
172
167
173
- pub inline fn fetchMax (self : * Self , value : T , comptime ordering : Ordering ) T {
174
- return self .rmw (.Max , value , ordering );
175
- }
176
- });
168
+ pub inline fn fetchMax (self : * Self , value : T , comptime ordering : Ordering ) T {
169
+ return self .rmw (.Max , value , ordering );
170
+ }
177
171
178
- pub usingnamespace exportWhen (std .meta .trait .isIntegral (T ), struct {
179
- pub inline fn fetchAnd (self : * Self , value : T , comptime ordering : Ordering ) T {
180
- return self .rmw (.And , value , ordering );
181
- }
172
+ pub inline fn fetchAnd (self : * Self , value : T , comptime ordering : Ordering ) T {
173
+ return self .rmw (.And , value , ordering );
174
+ }
182
175
183
- pub inline fn fetchNand (self : * Self , value : T , comptime ordering : Ordering ) T {
184
- return self .rmw (.Nand , value , ordering );
185
- }
176
+ pub inline fn fetchNand (self : * Self , value : T , comptime ordering : Ordering ) T {
177
+ return self .rmw (.Nand , value , ordering );
178
+ }
186
179
187
- pub inline fn fetchOr (self : * Self , value : T , comptime ordering : Ordering ) T {
188
- return self .rmw (.Or , value , ordering );
189
- }
180
+ pub inline fn fetchOr (self : * Self , value : T , comptime ordering : Ordering ) T {
181
+ return self .rmw (.Or , value , ordering );
182
+ }
190
183
191
- pub inline fn fetchXor (self : * Self , value : T , comptime ordering : Ordering ) T {
192
- return self .rmw (.Xor , value , ordering );
193
- }
184
+ pub inline fn fetchXor (self : * Self , value : T , comptime ordering : Ordering ) T {
185
+ return self .rmw (.Xor , value , ordering );
186
+ }
194
187
195
- const Bit = std .math .Log2Int (T );
196
- const BitRmwOp = enum {
197
- Set ,
198
- Reset ,
199
- Toggle ,
200
- };
188
+ const Bit = std .math .Log2Int (T );
189
+ const BitRmwOp = enum {
190
+ Set ,
191
+ Reset ,
192
+ Toggle ,
193
+ };
201
194
202
- pub inline fn bitSet (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
203
- return bitRmw (self , .Set , bit , ordering );
204
- }
195
+ pub inline fn bitSet (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
196
+ return bitRmw (self , .Set , bit , ordering );
197
+ }
205
198
206
- pub inline fn bitReset (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
207
- return bitRmw (self , .Reset , bit , ordering );
208
- }
199
+ pub inline fn bitReset (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
200
+ return bitRmw (self , .Reset , bit , ordering );
201
+ }
209
202
210
- pub inline fn bitToggle (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
211
- return bitRmw (self , .Toggle , bit , ordering );
212
- }
203
+ pub inline fn bitToggle (self : * Self , bit : Bit , comptime ordering : Ordering ) u1 {
204
+ return bitRmw (self , .Toggle , bit , ordering );
205
+ }
213
206
214
- inline fn bitRmw (self : * Self , comptime op : BitRmwOp , bit : Bit , comptime ordering : Ordering ) u1 {
215
- // x86 supports dedicated bitwise instructions
216
- if (comptime builtin .target .cpu .arch .isX86 () and @sizeOf (T ) >= 2 and @sizeOf (T ) <= 8 ) {
217
- // TODO: this causes std lib test failures when enabled
218
- if (false ) {
219
- return x86BitRmw (self , op , bit , ordering );
220
- }
207
+ inline fn bitRmw (self : * Self , comptime op : BitRmwOp , bit : Bit , comptime ordering : Ordering ) u1 {
208
+ // x86 supports dedicated bitwise instructions
209
+ 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
211
+ if (false ) {
212
+ return x86BitRmw (self , op , bit , ordering );
221
213
}
214
+ }
222
215
223
- const mask = @as (T , 1 ) << bit ;
224
- const value = switch (op ) {
225
- .Set = > self .fetchOr (mask , ordering ),
226
- .Reset = > self .fetchAnd (~ mask , ordering ),
227
- .Toggle = > self .fetchXor (mask , ordering ),
228
- };
216
+ const mask = @as (T , 1 ) << bit ;
217
+ const value = switch (op ) {
218
+ .Set = > self .fetchOr (mask , ordering ),
219
+ .Reset = > self .fetchAnd (~ mask , ordering ),
220
+ .Toggle = > self .fetchXor (mask , ordering ),
221
+ };
229
222
230
- return @intFromBool (value & mask != 0 );
231
- }
223
+ return @intFromBool (value & mask != 0 );
224
+ }
232
225
233
- inline fn x86BitRmw (self : * Self , comptime op : BitRmwOp , bit : Bit , comptime ordering : Ordering ) u1 {
234
- const old_bit : u8 = switch (@sizeOf (T )) {
235
- 2 = > switch (op ) {
236
- .Set = > asm volatile ("lock btsw %[bit], %[ptr]"
237
- // LLVM doesn't support u1 flag register return values
238
- : [result ] "={@ccc}" (- > u8 ),
239
- : [ptr ] "*m" (& self .value ),
240
- [bit ] "X" (@as (T , bit )),
241
- : "cc" , "memory"
242
- ),
243
- .Reset = > asm volatile ("lock btrw %[bit], %[ptr]"
244
- // LLVM doesn't support u1 flag register return values
245
- : [result ] "={@ccc}" (- > u8 ),
246
- : [ptr ] "*m" (& self .value ),
247
- [bit ] "X" (@as (T , bit )),
248
- : "cc" , "memory"
249
- ),
250
- .Toggle = > asm volatile ("lock btcw %[bit], %[ptr]"
251
- // LLVM doesn't support u1 flag register return values
252
- : [result ] "={@ccc}" (- > u8 ),
253
- : [ptr ] "*m" (& self .value ),
254
- [bit ] "X" (@as (T , bit )),
255
- : "cc" , "memory"
256
- ),
257
- },
258
- 4 = > switch (op ) {
259
- .Set = > asm volatile ("lock btsl %[bit], %[ptr]"
260
- // LLVM doesn't support u1 flag register return values
261
- : [result ] "={@ccc}" (- > u8 ),
262
- : [ptr ] "*m" (& self .value ),
263
- [bit ] "X" (@as (T , bit )),
264
- : "cc" , "memory"
265
- ),
266
- .Reset = > asm volatile ("lock btrl %[bit], %[ptr]"
267
- // LLVM doesn't support u1 flag register return values
268
- : [result ] "={@ccc}" (- > u8 ),
269
- : [ptr ] "*m" (& self .value ),
270
- [bit ] "X" (@as (T , bit )),
271
- : "cc" , "memory"
272
- ),
273
- .Toggle = > asm volatile ("lock btcl %[bit], %[ptr]"
274
- // LLVM doesn't support u1 flag register return values
275
- : [result ] "={@ccc}" (- > u8 ),
276
- : [ptr ] "*m" (& self .value ),
277
- [bit ] "X" (@as (T , bit )),
278
- : "cc" , "memory"
279
- ),
280
- },
281
- 8 = > switch (op ) {
282
- .Set = > asm volatile ("lock btsq %[bit], %[ptr]"
283
- // LLVM doesn't support u1 flag register return values
284
- : [result ] "={@ccc}" (- > u8 ),
285
- : [ptr ] "*m" (& self .value ),
286
- [bit ] "X" (@as (T , bit )),
287
- : "cc" , "memory"
288
- ),
289
- .Reset = > asm volatile ("lock btrq %[bit], %[ptr]"
290
- // LLVM doesn't support u1 flag register return values
291
- : [result ] "={@ccc}" (- > u8 ),
292
- : [ptr ] "*m" (& self .value ),
293
- [bit ] "X" (@as (T , bit )),
294
- : "cc" , "memory"
295
- ),
296
- .Toggle = > asm volatile ("lock btcq %[bit], %[ptr]"
297
- // LLVM doesn't support u1 flag register return values
298
- : [result ] "={@ccc}" (- > u8 ),
299
- : [ptr ] "*m" (& self .value ),
300
- [bit ] "X" (@as (T , bit )),
301
- : "cc" , "memory"
302
- ),
303
- },
304
- else = > @compileError ("Invalid atomic type " ++ @typeName (T )),
305
- };
226
+ inline fn x86BitRmw (self : * Self , comptime op : BitRmwOp , bit : Bit , comptime ordering : Ordering ) u1 {
227
+ const old_bit : u8 = switch (@sizeOf (T )) {
228
+ 2 = > switch (op ) {
229
+ .Set = > asm volatile ("lock btsw %[bit], %[ptr]"
230
+ // LLVM doesn't support u1 flag register return values
231
+ : [result ] "={@ccc}" (- > u8 ),
232
+ : [ptr ] "*m" (& self .value ),
233
+ [bit ] "X" (@as (T , bit )),
234
+ : "cc" , "memory"
235
+ ),
236
+ .Reset = > asm volatile ("lock btrw %[bit], %[ptr]"
237
+ // LLVM doesn't support u1 flag register return values
238
+ : [result ] "={@ccc}" (- > u8 ),
239
+ : [ptr ] "*m" (& self .value ),
240
+ [bit ] "X" (@as (T , bit )),
241
+ : "cc" , "memory"
242
+ ),
243
+ .Toggle = > asm volatile ("lock btcw %[bit], %[ptr]"
244
+ // LLVM doesn't support u1 flag register return values
245
+ : [result ] "={@ccc}" (- > u8 ),
246
+ : [ptr ] "*m" (& self .value ),
247
+ [bit ] "X" (@as (T , bit )),
248
+ : "cc" , "memory"
249
+ ),
250
+ },
251
+ 4 = > switch (op ) {
252
+ .Set = > asm volatile ("lock btsl %[bit], %[ptr]"
253
+ // LLVM doesn't support u1 flag register return values
254
+ : [result ] "={@ccc}" (- > u8 ),
255
+ : [ptr ] "*m" (& self .value ),
256
+ [bit ] "X" (@as (T , bit )),
257
+ : "cc" , "memory"
258
+ ),
259
+ .Reset = > asm volatile ("lock btrl %[bit], %[ptr]"
260
+ // LLVM doesn't support u1 flag register return values
261
+ : [result ] "={@ccc}" (- > u8 ),
262
+ : [ptr ] "*m" (& self .value ),
263
+ [bit ] "X" (@as (T , bit )),
264
+ : "cc" , "memory"
265
+ ),
266
+ .Toggle = > asm volatile ("lock btcl %[bit], %[ptr]"
267
+ // LLVM doesn't support u1 flag register return values
268
+ : [result ] "={@ccc}" (- > u8 ),
269
+ : [ptr ] "*m" (& self .value ),
270
+ [bit ] "X" (@as (T , bit )),
271
+ : "cc" , "memory"
272
+ ),
273
+ },
274
+ 8 = > switch (op ) {
275
+ .Set = > asm volatile ("lock btsq %[bit], %[ptr]"
276
+ // LLVM doesn't support u1 flag register return values
277
+ : [result ] "={@ccc}" (- > u8 ),
278
+ : [ptr ] "*m" (& self .value ),
279
+ [bit ] "X" (@as (T , bit )),
280
+ : "cc" , "memory"
281
+ ),
282
+ .Reset = > asm volatile ("lock btrq %[bit], %[ptr]"
283
+ // LLVM doesn't support u1 flag register return values
284
+ : [result ] "={@ccc}" (- > u8 ),
285
+ : [ptr ] "*m" (& self .value ),
286
+ [bit ] "X" (@as (T , bit )),
287
+ : "cc" , "memory"
288
+ ),
289
+ .Toggle = > asm volatile ("lock btcq %[bit], %[ptr]"
290
+ // LLVM doesn't support u1 flag register return values
291
+ : [result ] "={@ccc}" (- > u8 ),
292
+ : [ptr ] "*m" (& self .value ),
293
+ [bit ] "X" (@as (T , bit )),
294
+ : "cc" , "memory"
295
+ ),
296
+ },
297
+ else = > @compileError ("Invalid atomic type " ++ @typeName (T )),
298
+ };
306
299
307
- // TODO: emit appropriate tsan fence if compiling with tsan
308
- _ = ordering ;
300
+ // TODO: emit appropriate tsan fence if compiling with tsan
301
+ _ = ordering ;
309
302
310
- return @as (u1 , @intCast (old_bit ));
311
- }
312
- });
303
+ return @intCast (old_bit );
304
+ }
313
305
};
314
306
}
315
307
0 commit comments