| ... | ... | @@ -24,6 +24,13 @@ const supports_atomic_ops = switch (arch) { |
| 24 | 24 | // load/store atomically. |
| 25 | 25 | // Objects bigger than this threshold require the use of a lock. |
| 26 | 26 | const largest_atomic_size = switch (arch) { |
| 27 | // On SPARC systems that lacks CAS and/or swap instructions, the only |
| 28 | // available atomic operation is a test-and-set (`ldstub`), so we force |
| 29 | // every atomic memory access to go through the lock. |
| 30 | // XXX: Check the presence of CAS/swap instructions and set this parameter |
| 31 | // accordingly. |
| 32 | .sparc, .sparcel, .sparcv9 => 0, |
| 33 | |
| 27 | 34 | // XXX: On x86/x86_64 we could check the presence of cmpxchg8b/cmpxchg16b |
| 28 | 35 | // and set this parameter accordingly. |
| 29 | 36 | else => @sizeOf(usize), |
| ... | ... | @@ -38,18 +45,35 @@ const SpinlockTable = struct { |
| 38 | 45 | const Spinlock = struct { |
| 39 | 46 | // Prevent false sharing by providing enough padding between two |
| 40 | 47 | // consecutive spinlock elements |
| 41 | | v: enum(usize) { Unlocked = 0, Locked } align(cache_line_size) = .Unlocked, |
| 48 | v: if (arch.isSPARC()) enum(u8) { Unlocked = 0, Locked = 255 } else enum(usize) { Unlocked = 0, Locked } align(cache_line_size) = .Unlocked, |
| 42 | 49 | |
| 43 | 50 | fn acquire(self: *@This()) void { |
| 44 | 51 | while (true) { |
| 45 | | switch (@atomicRmw(@TypeOf(self.v), &self.v, .Xchg, .Locked, .Acquire)) { |
| 52 | const flag = if (comptime arch.isSPARC()) |
| 53 | asm volatile ("ldstub [%[addr]], %[flag]" |
| 54 | : [flag] "=r" (-> @TypeOf(self.v)), |
| 55 | : [addr] "r" (&self.v), |
| 56 | : "memory" |
| 57 | ) |
| 58 | else |
| 59 | @atomicRmw(@TypeOf(self.v), &self.v, .Xchg, .Locked, .Acquire); |
| 60 | |
| 61 | switch (flag) { |
| 46 | 62 | .Unlocked => break, |
| 47 | 63 | .Locked => {}, |
| 48 | 64 | } |
| 49 | 65 | } |
| 50 | 66 | } |
| 51 | 67 | fn release(self: *@This()) void { |
| 52 | | @atomicStore(@TypeOf(self.v), &self.v, .Unlocked, .Release); |
| 68 | if (comptime arch.isSPARC()) { |
| 69 | _ = asm volatile ("clr [%[addr]]" |
| 70 | : |
| 71 | : [addr] "r" (&self.v), |
| 72 | : "memory" |
| 73 | ); |
| 74 | } else { |
| 75 | @atomicStore(@TypeOf(self.v), &self.v, .Unlocked, .Release); |
| 76 | } |
| 53 | 77 | } |
| 54 | 78 | }; |
| 55 | 79 | |