Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include "mozilla/Assertions.h" |
michael@0 | 6 | #include "mozilla/Atomics.h" |
michael@0 | 7 | |
michael@0 | 8 | #include <stdint.h> |
michael@0 | 9 | |
michael@0 | 10 | using mozilla::Atomic; |
michael@0 | 11 | using mozilla::MemoryOrdering; |
michael@0 | 12 | using mozilla::Relaxed; |
michael@0 | 13 | using mozilla::ReleaseAcquire; |
michael@0 | 14 | using mozilla::SequentiallyConsistent; |
michael@0 | 15 | |
michael@0 | 16 | template <typename T, MemoryOrdering Order> |
michael@0 | 17 | static void |
michael@0 | 18 | TestTypeWithOrdering() |
michael@0 | 19 | { |
michael@0 | 20 | Atomic<T, Order> atomic(5); |
michael@0 | 21 | MOZ_RELEASE_ASSERT(atomic == 5, "Atomic variable did not initialize"); |
michael@0 | 22 | |
michael@0 | 23 | // Test atomic increment |
michael@0 | 24 | MOZ_RELEASE_ASSERT(++atomic == T(6), "Atomic increment did not work"); |
michael@0 | 25 | MOZ_RELEASE_ASSERT(atomic++ == T(6), "Atomic post-increment did not work"); |
michael@0 | 26 | MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic post-increment did not work"); |
michael@0 | 27 | |
michael@0 | 28 | // Test atomic decrement |
michael@0 | 29 | MOZ_RELEASE_ASSERT(--atomic == 6, "Atomic decrement did not work"); |
michael@0 | 30 | MOZ_RELEASE_ASSERT(atomic-- == 6, "Atomic post-decrement did not work"); |
michael@0 | 31 | MOZ_RELEASE_ASSERT(atomic == 5, "Atomic post-decrement did not work"); |
michael@0 | 32 | |
michael@0 | 33 | // Test other arithmetic. |
michael@0 | 34 | T result; |
michael@0 | 35 | result = (atomic += T(5)); |
michael@0 | 36 | MOZ_RELEASE_ASSERT(atomic == T(10), "Atomic += did not work"); |
michael@0 | 37 | MOZ_RELEASE_ASSERT(result == T(10), "Atomic += returned the wrong value"); |
michael@0 | 38 | result = (atomic -= T(3)); |
michael@0 | 39 | MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic -= did not work"); |
michael@0 | 40 | MOZ_RELEASE_ASSERT(result == T(7), "Atomic -= returned the wrong value"); |
michael@0 | 41 | |
michael@0 | 42 | // Test assignment |
michael@0 | 43 | result = (atomic = T(5)); |
michael@0 | 44 | MOZ_RELEASE_ASSERT(atomic == T(5), "Atomic assignment failed"); |
michael@0 | 45 | MOZ_RELEASE_ASSERT(result == T(5), "Atomic assignment returned the wrong value"); |
michael@0 | 46 | |
michael@0 | 47 | // Test logical operations. |
michael@0 | 48 | result = (atomic ^= T(2)); |
michael@0 | 49 | MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic ^= did not work"); |
michael@0 | 50 | MOZ_RELEASE_ASSERT(result == T(7), "Atomic ^= returned the wrong value"); |
michael@0 | 51 | result = (atomic ^= T(4)); |
michael@0 | 52 | MOZ_RELEASE_ASSERT(atomic == T(3), "Atomic ^= did not work"); |
michael@0 | 53 | MOZ_RELEASE_ASSERT(result == T(3), "Atomic ^= returned the wrong value"); |
michael@0 | 54 | result = (atomic |= T(8)); |
michael@0 | 55 | MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); |
michael@0 | 56 | MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); |
michael@0 | 57 | result = (atomic |= T(8)); |
michael@0 | 58 | MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); |
michael@0 | 59 | MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); |
michael@0 | 60 | result = (atomic &= T(12)); |
michael@0 | 61 | MOZ_RELEASE_ASSERT(atomic == T(8), "Atomic &= did not work"); |
michael@0 | 62 | MOZ_RELEASE_ASSERT(result == T(8), "Atomic &= returned the wrong value"); |
michael@0 | 63 | |
michael@0 | 64 | // Test exchange. |
michael@0 | 65 | atomic = T(30); |
michael@0 | 66 | result = atomic.exchange(42); |
michael@0 | 67 | MOZ_RELEASE_ASSERT(atomic == T(42), "Atomic exchange did not work"); |
michael@0 | 68 | MOZ_RELEASE_ASSERT(result == T(30), "Atomic exchange returned the wrong value"); |
michael@0 | 69 | |
michael@0 | 70 | // Test CAS. |
michael@0 | 71 | atomic = T(1); |
michael@0 | 72 | bool boolResult = atomic.compareExchange(0, 2); |
michael@0 | 73 | MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
michael@0 | 74 | MOZ_RELEASE_ASSERT(atomic == T(1), "CAS shouldn't have done anything."); |
michael@0 | 75 | |
michael@0 | 76 | boolResult = atomic.compareExchange(1, 42); |
michael@0 | 77 | MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
michael@0 | 78 | MOZ_RELEASE_ASSERT(atomic == T(42), "CAS should have changed atomic's value."); |
michael@0 | 79 | } |
michael@0 | 80 | |
michael@0 | 81 | template<typename T, MemoryOrdering Order> |
michael@0 | 82 | static void |
michael@0 | 83 | TestPointerWithOrdering() |
michael@0 | 84 | { |
michael@0 | 85 | T array1[10]; |
michael@0 | 86 | Atomic<T*, Order> atomic(array1); |
michael@0 | 87 | MOZ_RELEASE_ASSERT(atomic == array1, "Atomic variable did not initialize"); |
michael@0 | 88 | |
michael@0 | 89 | // Test atomic increment |
michael@0 | 90 | MOZ_RELEASE_ASSERT(++atomic == array1 + 1, "Atomic increment did not work"); |
michael@0 | 91 | MOZ_RELEASE_ASSERT(atomic++ == array1 + 1, "Atomic post-increment did not work"); |
michael@0 | 92 | MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic post-increment did not work"); |
michael@0 | 93 | |
michael@0 | 94 | // Test atomic decrement |
michael@0 | 95 | MOZ_RELEASE_ASSERT(--atomic == array1 + 1, "Atomic decrement did not work"); |
michael@0 | 96 | MOZ_RELEASE_ASSERT(atomic-- == array1 + 1, "Atomic post-decrement did not work"); |
michael@0 | 97 | MOZ_RELEASE_ASSERT(atomic == array1, "Atomic post-decrement did not work"); |
michael@0 | 98 | |
michael@0 | 99 | // Test other arithmetic operations |
michael@0 | 100 | T* result; |
michael@0 | 101 | result = (atomic += 2); |
michael@0 | 102 | MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic += did not work"); |
michael@0 | 103 | MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic += returned the wrong value"); |
michael@0 | 104 | result = (atomic -= 1); |
michael@0 | 105 | MOZ_RELEASE_ASSERT(atomic == array1 + 1, "Atomic -= did not work"); |
michael@0 | 106 | MOZ_RELEASE_ASSERT(result == array1 + 1, "Atomic -= returned the wrong value"); |
michael@0 | 107 | |
michael@0 | 108 | // Test stores |
michael@0 | 109 | result = (atomic = array1); |
michael@0 | 110 | MOZ_RELEASE_ASSERT(atomic == array1, "Atomic assignment did not work"); |
michael@0 | 111 | MOZ_RELEASE_ASSERT(result == array1, "Atomic assignment returned the wrong value"); |
michael@0 | 112 | |
michael@0 | 113 | // Test exchange |
michael@0 | 114 | atomic = array1 + 2; |
michael@0 | 115 | result = atomic.exchange(array1); |
michael@0 | 116 | MOZ_RELEASE_ASSERT(atomic == array1, "Atomic exchange did not work"); |
michael@0 | 117 | MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic exchange returned the wrong value"); |
michael@0 | 118 | |
michael@0 | 119 | atomic = array1; |
michael@0 | 120 | bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2); |
michael@0 | 121 | MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
michael@0 | 122 | MOZ_RELEASE_ASSERT(atomic == array1, "CAS shouldn't have done anything."); |
michael@0 | 123 | |
michael@0 | 124 | boolResult = atomic.compareExchange(array1, array1 + 3); |
michael@0 | 125 | MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
michael@0 | 126 | MOZ_RELEASE_ASSERT(atomic == array1 + 3, "CAS should have changed atomic's value."); |
michael@0 | 127 | } |
michael@0 | 128 | |
michael@0 | 129 | enum EnumType { |
michael@0 | 130 | EnumType_0 = 0, |
michael@0 | 131 | EnumType_1 = 1, |
michael@0 | 132 | EnumType_2 = 2, |
michael@0 | 133 | EnumType_3 = 3 |
michael@0 | 134 | }; |
michael@0 | 135 | |
michael@0 | 136 | template<MemoryOrdering Order> |
michael@0 | 137 | static void |
michael@0 | 138 | TestEnumWithOrdering() |
michael@0 | 139 | { |
michael@0 | 140 | Atomic<EnumType, Order> atomic(EnumType_2); |
michael@0 | 141 | MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic variable did not initialize"); |
michael@0 | 142 | |
michael@0 | 143 | // Test assignment |
michael@0 | 144 | EnumType result; |
michael@0 | 145 | result = (atomic = EnumType_3); |
michael@0 | 146 | MOZ_RELEASE_ASSERT(atomic == EnumType_3, "Atomic assignment failed"); |
michael@0 | 147 | MOZ_RELEASE_ASSERT(result == EnumType_3, "Atomic assignment returned the wrong value"); |
michael@0 | 148 | |
michael@0 | 149 | // Test exchange. |
michael@0 | 150 | atomic = EnumType_1; |
michael@0 | 151 | result = atomic.exchange(EnumType_2); |
michael@0 | 152 | MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic exchange did not work"); |
michael@0 | 153 | MOZ_RELEASE_ASSERT(result == EnumType_1, "Atomic exchange returned the wrong value"); |
michael@0 | 154 | |
michael@0 | 155 | // Test CAS. |
michael@0 | 156 | atomic = EnumType_1; |
michael@0 | 157 | bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2); |
michael@0 | 158 | MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
michael@0 | 159 | MOZ_RELEASE_ASSERT(atomic == EnumType_1, "CAS shouldn't have done anything."); |
michael@0 | 160 | |
michael@0 | 161 | boolResult = atomic.compareExchange(EnumType_1, EnumType_3); |
michael@0 | 162 | MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
michael@0 | 163 | MOZ_RELEASE_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value."); |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | template <MemoryOrdering Order> |
michael@0 | 167 | static void |
michael@0 | 168 | TestBoolWithOrdering() |
michael@0 | 169 | { |
michael@0 | 170 | Atomic<bool, Order> atomic(false); |
michael@0 | 171 | MOZ_RELEASE_ASSERT(atomic == false, "Atomic variable did not initialize"); |
michael@0 | 172 | |
michael@0 | 173 | // Test assignment |
michael@0 | 174 | bool result; |
michael@0 | 175 | result = (atomic = true); |
michael@0 | 176 | MOZ_RELEASE_ASSERT(atomic == true, "Atomic assignment failed"); |
michael@0 | 177 | MOZ_RELEASE_ASSERT(result == true, "Atomic assignment returned the wrong value"); |
michael@0 | 178 | |
michael@0 | 179 | // Test exchange. |
michael@0 | 180 | atomic = false; |
michael@0 | 181 | result = atomic.exchange(true); |
michael@0 | 182 | MOZ_RELEASE_ASSERT(atomic == true, "Atomic exchange did not work"); |
michael@0 | 183 | MOZ_RELEASE_ASSERT(result == false, "Atomic exchange returned the wrong value"); |
michael@0 | 184 | |
michael@0 | 185 | // Test CAS. |
michael@0 | 186 | atomic = false; |
michael@0 | 187 | bool boolResult = atomic.compareExchange(true, false); |
michael@0 | 188 | MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); |
michael@0 | 189 | MOZ_RELEASE_ASSERT(atomic == false, "CAS shouldn't have done anything."); |
michael@0 | 190 | |
michael@0 | 191 | boolResult = atomic.compareExchange(false, true); |
michael@0 | 192 | MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); |
michael@0 | 193 | MOZ_RELEASE_ASSERT(atomic == true, "CAS should have changed atomic's value."); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | template <typename T> |
michael@0 | 197 | static void |
michael@0 | 198 | TestType() |
michael@0 | 199 | { |
michael@0 | 200 | TestTypeWithOrdering<T, SequentiallyConsistent>(); |
michael@0 | 201 | TestTypeWithOrdering<T, ReleaseAcquire>(); |
michael@0 | 202 | TestTypeWithOrdering<T, Relaxed>(); |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | template<typename T> |
michael@0 | 206 | static void |
michael@0 | 207 | TestPointer() |
michael@0 | 208 | { |
michael@0 | 209 | TestPointerWithOrdering<T, SequentiallyConsistent>(); |
michael@0 | 210 | TestPointerWithOrdering<T, ReleaseAcquire>(); |
michael@0 | 211 | TestPointerWithOrdering<T, Relaxed>(); |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | static void |
michael@0 | 215 | TestEnum() |
michael@0 | 216 | { |
michael@0 | 217 | TestEnumWithOrdering<SequentiallyConsistent>(); |
michael@0 | 218 | TestEnumWithOrdering<ReleaseAcquire>(); |
michael@0 | 219 | TestEnumWithOrdering<Relaxed>(); |
michael@0 | 220 | } |
michael@0 | 221 | |
michael@0 | 222 | static void |
michael@0 | 223 | TestBool() |
michael@0 | 224 | { |
michael@0 | 225 | TestBoolWithOrdering<SequentiallyConsistent>(); |
michael@0 | 226 | TestBoolWithOrdering<ReleaseAcquire>(); |
michael@0 | 227 | TestBoolWithOrdering<Relaxed>(); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | int main() |
michael@0 | 231 | { |
michael@0 | 232 | TestType<uint32_t>(); |
michael@0 | 233 | TestType<int32_t>(); |
michael@0 | 234 | TestType<intptr_t>(); |
michael@0 | 235 | TestType<uintptr_t>(); |
michael@0 | 236 | TestPointer<int>(); |
michael@0 | 237 | TestPointer<float>(); |
michael@0 | 238 | TestPointer<uint16_t*>(); |
michael@0 | 239 | TestPointer<uint32_t*>(); |
michael@0 | 240 | TestEnum(); |
michael@0 | 241 | TestBool(); |
michael@0 | 242 | } |