diff options
Diffstat (limited to 'src/common/atomic_ops.h')
| -rw-r--r-- | src/common/atomic_ops.h | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index b94d73c7a..69fde8421 100644 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h | |||
| @@ -46,6 +46,50 @@ namespace Common { | |||
| 46 | reinterpret_cast<__int64*>(expected.data())) != 0; | 46 | reinterpret_cast<__int64*>(expected.data())) != 0; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected, | ||
| 50 | u8& actual) { | ||
| 51 | actual = | ||
| 52 | _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected); | ||
| 53 | return actual == expected; | ||
| 54 | } | ||
| 55 | |||
| 56 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected, | ||
| 57 | u16& actual) { | ||
| 58 | actual = | ||
| 59 | _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected); | ||
| 60 | return actual == expected; | ||
| 61 | } | ||
| 62 | |||
| 63 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected, | ||
| 64 | u32& actual) { | ||
| 65 | actual = | ||
| 66 | _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected); | ||
| 67 | return actual == expected; | ||
| 68 | } | ||
| 69 | |||
| 70 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected, | ||
| 71 | u64& actual) { | ||
| 72 | actual = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer), value, | ||
| 73 | expected); | ||
| 74 | return actual == expected; | ||
| 75 | } | ||
| 76 | |||
| 77 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected, | ||
| 78 | u128& actual) { | ||
| 79 | const bool result = | ||
| 80 | _InterlockedCompareExchange128(reinterpret_cast<volatile __int64*>(pointer), value[1], | ||
| 81 | value[0], reinterpret_cast<__int64*>(expected.data())) != 0; | ||
| 82 | actual = expected; | ||
| 83 | return result; | ||
| 84 | } | ||
| 85 | |||
| 86 | [[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { | ||
| 87 | u128 result{}; | ||
| 88 | _InterlockedCompareExchange128(reinterpret_cast<volatile __int64*>(pointer), result[1], | ||
| 89 | result[0], reinterpret_cast<__int64*>(result.data())); | ||
| 90 | return result; | ||
| 91 | } | ||
| 92 | |||
| 49 | #else | 93 | #else |
| 50 | 94 | ||
| 51 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { | 95 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { |
| @@ -72,6 +116,52 @@ namespace Common { | |||
| 72 | return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); | 116 | return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); |
| 73 | } | 117 | } |
| 74 | 118 | ||
| 119 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected, | ||
| 120 | u8& actual) { | ||
| 121 | actual = __sync_val_compare_and_swap(pointer, expected, value); | ||
| 122 | return actual == expected; | ||
| 123 | } | ||
| 124 | |||
| 125 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected, | ||
| 126 | u16& actual) { | ||
| 127 | actual = __sync_val_compare_and_swap(pointer, expected, value); | ||
| 128 | return actual == expected; | ||
| 129 | } | ||
| 130 | |||
| 131 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected, | ||
| 132 | u32& actual) { | ||
| 133 | actual = __sync_val_compare_and_swap(pointer, expected, value); | ||
| 134 | return actual == expected; | ||
| 135 | } | ||
| 136 | |||
| 137 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected, | ||
| 138 | u64& actual) { | ||
| 139 | actual = __sync_val_compare_and_swap(pointer, expected, value); | ||
| 140 | return actual == expected; | ||
| 141 | } | ||
| 142 | |||
| 143 | [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected, | ||
| 144 | u128& actual) { | ||
| 145 | unsigned __int128 value_a; | ||
| 146 | unsigned __int128 expected_a; | ||
| 147 | unsigned __int128 actual_a; | ||
| 148 | std::memcpy(&value_a, value.data(), sizeof(u128)); | ||
| 149 | std::memcpy(&expected_a, expected.data(), sizeof(u128)); | ||
| 150 | actual_a = __sync_val_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a); | ||
| 151 | std::memcpy(actual.data(), &actual_a, sizeof(u128)); | ||
| 152 | return actual_a == expected_a; | ||
| 153 | } | ||
| 154 | |||
| 155 | [[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { | ||
| 156 | unsigned __int128 zeros_a = 0; | ||
| 157 | unsigned __int128 result_a = | ||
| 158 | __sync_val_compare_and_swap((unsigned __int128*)pointer, zeros_a, zeros_a); | ||
| 159 | |||
| 160 | u128 result; | ||
| 161 | std::memcpy(result.data(), &result_a, sizeof(u128)); | ||
| 162 | return result; | ||
| 163 | } | ||
| 164 | |||
| 75 | #endif | 165 | #endif |
| 76 | 166 | ||
| 77 | } // namespace Common | 167 | } // namespace Common |