mfbt/tests/TestAtomics.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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 }

mercurial