1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mfbt/tests/TestAtomics.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,242 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "mozilla/Assertions.h" 1.9 +#include "mozilla/Atomics.h" 1.10 + 1.11 +#include <stdint.h> 1.12 + 1.13 +using mozilla::Atomic; 1.14 +using mozilla::MemoryOrdering; 1.15 +using mozilla::Relaxed; 1.16 +using mozilla::ReleaseAcquire; 1.17 +using mozilla::SequentiallyConsistent; 1.18 + 1.19 +template <typename T, MemoryOrdering Order> 1.20 +static void 1.21 +TestTypeWithOrdering() 1.22 +{ 1.23 + Atomic<T, Order> atomic(5); 1.24 + MOZ_RELEASE_ASSERT(atomic == 5, "Atomic variable did not initialize"); 1.25 + 1.26 + // Test atomic increment 1.27 + MOZ_RELEASE_ASSERT(++atomic == T(6), "Atomic increment did not work"); 1.28 + MOZ_RELEASE_ASSERT(atomic++ == T(6), "Atomic post-increment did not work"); 1.29 + MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic post-increment did not work"); 1.30 + 1.31 + // Test atomic decrement 1.32 + MOZ_RELEASE_ASSERT(--atomic == 6, "Atomic decrement did not work"); 1.33 + MOZ_RELEASE_ASSERT(atomic-- == 6, "Atomic post-decrement did not work"); 1.34 + MOZ_RELEASE_ASSERT(atomic == 5, "Atomic post-decrement did not work"); 1.35 + 1.36 + // Test other arithmetic. 1.37 + T result; 1.38 + result = (atomic += T(5)); 1.39 + MOZ_RELEASE_ASSERT(atomic == T(10), "Atomic += did not work"); 1.40 + MOZ_RELEASE_ASSERT(result == T(10), "Atomic += returned the wrong value"); 1.41 + result = (atomic -= T(3)); 1.42 + MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic -= did not work"); 1.43 + MOZ_RELEASE_ASSERT(result == T(7), "Atomic -= returned the wrong value"); 1.44 + 1.45 + // Test assignment 1.46 + result = (atomic = T(5)); 1.47 + MOZ_RELEASE_ASSERT(atomic == T(5), "Atomic assignment failed"); 1.48 + MOZ_RELEASE_ASSERT(result == T(5), "Atomic assignment returned the wrong value"); 1.49 + 1.50 + // Test logical operations. 1.51 + result = (atomic ^= T(2)); 1.52 + MOZ_RELEASE_ASSERT(atomic == T(7), "Atomic ^= did not work"); 1.53 + MOZ_RELEASE_ASSERT(result == T(7), "Atomic ^= returned the wrong value"); 1.54 + result = (atomic ^= T(4)); 1.55 + MOZ_RELEASE_ASSERT(atomic == T(3), "Atomic ^= did not work"); 1.56 + MOZ_RELEASE_ASSERT(result == T(3), "Atomic ^= returned the wrong value"); 1.57 + result = (atomic |= T(8)); 1.58 + MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); 1.59 + MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); 1.60 + result = (atomic |= T(8)); 1.61 + MOZ_RELEASE_ASSERT(atomic == T(11), "Atomic |= did not work"); 1.62 + MOZ_RELEASE_ASSERT(result == T(11), "Atomic |= returned the wrong value"); 1.63 + result = (atomic &= T(12)); 1.64 + MOZ_RELEASE_ASSERT(atomic == T(8), "Atomic &= did not work"); 1.65 + MOZ_RELEASE_ASSERT(result == T(8), "Atomic &= returned the wrong value"); 1.66 + 1.67 + // Test exchange. 1.68 + atomic = T(30); 1.69 + result = atomic.exchange(42); 1.70 + MOZ_RELEASE_ASSERT(atomic == T(42), "Atomic exchange did not work"); 1.71 + MOZ_RELEASE_ASSERT(result == T(30), "Atomic exchange returned the wrong value"); 1.72 + 1.73 + // Test CAS. 1.74 + atomic = T(1); 1.75 + bool boolResult = atomic.compareExchange(0, 2); 1.76 + MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); 1.77 + MOZ_RELEASE_ASSERT(atomic == T(1), "CAS shouldn't have done anything."); 1.78 + 1.79 + boolResult = atomic.compareExchange(1, 42); 1.80 + MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); 1.81 + MOZ_RELEASE_ASSERT(atomic == T(42), "CAS should have changed atomic's value."); 1.82 +} 1.83 + 1.84 +template<typename T, MemoryOrdering Order> 1.85 +static void 1.86 +TestPointerWithOrdering() 1.87 +{ 1.88 + T array1[10]; 1.89 + Atomic<T*, Order> atomic(array1); 1.90 + MOZ_RELEASE_ASSERT(atomic == array1, "Atomic variable did not initialize"); 1.91 + 1.92 + // Test atomic increment 1.93 + MOZ_RELEASE_ASSERT(++atomic == array1 + 1, "Atomic increment did not work"); 1.94 + MOZ_RELEASE_ASSERT(atomic++ == array1 + 1, "Atomic post-increment did not work"); 1.95 + MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic post-increment did not work"); 1.96 + 1.97 + // Test atomic decrement 1.98 + MOZ_RELEASE_ASSERT(--atomic == array1 + 1, "Atomic decrement did not work"); 1.99 + MOZ_RELEASE_ASSERT(atomic-- == array1 + 1, "Atomic post-decrement did not work"); 1.100 + MOZ_RELEASE_ASSERT(atomic == array1, "Atomic post-decrement did not work"); 1.101 + 1.102 + // Test other arithmetic operations 1.103 + T* result; 1.104 + result = (atomic += 2); 1.105 + MOZ_RELEASE_ASSERT(atomic == array1 + 2, "Atomic += did not work"); 1.106 + MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic += returned the wrong value"); 1.107 + result = (atomic -= 1); 1.108 + MOZ_RELEASE_ASSERT(atomic == array1 + 1, "Atomic -= did not work"); 1.109 + MOZ_RELEASE_ASSERT(result == array1 + 1, "Atomic -= returned the wrong value"); 1.110 + 1.111 + // Test stores 1.112 + result = (atomic = array1); 1.113 + MOZ_RELEASE_ASSERT(atomic == array1, "Atomic assignment did not work"); 1.114 + MOZ_RELEASE_ASSERT(result == array1, "Atomic assignment returned the wrong value"); 1.115 + 1.116 + // Test exchange 1.117 + atomic = array1 + 2; 1.118 + result = atomic.exchange(array1); 1.119 + MOZ_RELEASE_ASSERT(atomic == array1, "Atomic exchange did not work"); 1.120 + MOZ_RELEASE_ASSERT(result == array1 + 2, "Atomic exchange returned the wrong value"); 1.121 + 1.122 + atomic = array1; 1.123 + bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2); 1.124 + MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); 1.125 + MOZ_RELEASE_ASSERT(atomic == array1, "CAS shouldn't have done anything."); 1.126 + 1.127 + boolResult = atomic.compareExchange(array1, array1 + 3); 1.128 + MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); 1.129 + MOZ_RELEASE_ASSERT(atomic == array1 + 3, "CAS should have changed atomic's value."); 1.130 +} 1.131 + 1.132 +enum EnumType { 1.133 + EnumType_0 = 0, 1.134 + EnumType_1 = 1, 1.135 + EnumType_2 = 2, 1.136 + EnumType_3 = 3 1.137 +}; 1.138 + 1.139 +template<MemoryOrdering Order> 1.140 +static void 1.141 +TestEnumWithOrdering() 1.142 +{ 1.143 + Atomic<EnumType, Order> atomic(EnumType_2); 1.144 + MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic variable did not initialize"); 1.145 + 1.146 + // Test assignment 1.147 + EnumType result; 1.148 + result = (atomic = EnumType_3); 1.149 + MOZ_RELEASE_ASSERT(atomic == EnumType_3, "Atomic assignment failed"); 1.150 + MOZ_RELEASE_ASSERT(result == EnumType_3, "Atomic assignment returned the wrong value"); 1.151 + 1.152 + // Test exchange. 1.153 + atomic = EnumType_1; 1.154 + result = atomic.exchange(EnumType_2); 1.155 + MOZ_RELEASE_ASSERT(atomic == EnumType_2, "Atomic exchange did not work"); 1.156 + MOZ_RELEASE_ASSERT(result == EnumType_1, "Atomic exchange returned the wrong value"); 1.157 + 1.158 + // Test CAS. 1.159 + atomic = EnumType_1; 1.160 + bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2); 1.161 + MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); 1.162 + MOZ_RELEASE_ASSERT(atomic == EnumType_1, "CAS shouldn't have done anything."); 1.163 + 1.164 + boolResult = atomic.compareExchange(EnumType_1, EnumType_3); 1.165 + MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); 1.166 + MOZ_RELEASE_ASSERT(atomic == EnumType_3, "CAS should have changed atomic's value."); 1.167 +} 1.168 + 1.169 +template <MemoryOrdering Order> 1.170 +static void 1.171 +TestBoolWithOrdering() 1.172 +{ 1.173 + Atomic<bool, Order> atomic(false); 1.174 + MOZ_RELEASE_ASSERT(atomic == false, "Atomic variable did not initialize"); 1.175 + 1.176 + // Test assignment 1.177 + bool result; 1.178 + result = (atomic = true); 1.179 + MOZ_RELEASE_ASSERT(atomic == true, "Atomic assignment failed"); 1.180 + MOZ_RELEASE_ASSERT(result == true, "Atomic assignment returned the wrong value"); 1.181 + 1.182 + // Test exchange. 1.183 + atomic = false; 1.184 + result = atomic.exchange(true); 1.185 + MOZ_RELEASE_ASSERT(atomic == true, "Atomic exchange did not work"); 1.186 + MOZ_RELEASE_ASSERT(result == false, "Atomic exchange returned the wrong value"); 1.187 + 1.188 + // Test CAS. 1.189 + atomic = false; 1.190 + bool boolResult = atomic.compareExchange(true, false); 1.191 + MOZ_RELEASE_ASSERT(!boolResult, "CAS should have returned false."); 1.192 + MOZ_RELEASE_ASSERT(atomic == false, "CAS shouldn't have done anything."); 1.193 + 1.194 + boolResult = atomic.compareExchange(false, true); 1.195 + MOZ_RELEASE_ASSERT(boolResult, "CAS should have succeeded."); 1.196 + MOZ_RELEASE_ASSERT(atomic == true, "CAS should have changed atomic's value."); 1.197 +} 1.198 + 1.199 +template <typename T> 1.200 +static void 1.201 +TestType() 1.202 +{ 1.203 + TestTypeWithOrdering<T, SequentiallyConsistent>(); 1.204 + TestTypeWithOrdering<T, ReleaseAcquire>(); 1.205 + TestTypeWithOrdering<T, Relaxed>(); 1.206 +} 1.207 + 1.208 +template<typename T> 1.209 +static void 1.210 +TestPointer() 1.211 +{ 1.212 + TestPointerWithOrdering<T, SequentiallyConsistent>(); 1.213 + TestPointerWithOrdering<T, ReleaseAcquire>(); 1.214 + TestPointerWithOrdering<T, Relaxed>(); 1.215 +} 1.216 + 1.217 +static void 1.218 +TestEnum() 1.219 +{ 1.220 + TestEnumWithOrdering<SequentiallyConsistent>(); 1.221 + TestEnumWithOrdering<ReleaseAcquire>(); 1.222 + TestEnumWithOrdering<Relaxed>(); 1.223 +} 1.224 + 1.225 +static void 1.226 +TestBool() 1.227 +{ 1.228 + TestBoolWithOrdering<SequentiallyConsistent>(); 1.229 + TestBoolWithOrdering<ReleaseAcquire>(); 1.230 + TestBoolWithOrdering<Relaxed>(); 1.231 +} 1.232 + 1.233 +int main() 1.234 +{ 1.235 + TestType<uint32_t>(); 1.236 + TestType<int32_t>(); 1.237 + TestType<intptr_t>(); 1.238 + TestType<uintptr_t>(); 1.239 + TestPointer<int>(); 1.240 + TestPointer<float>(); 1.241 + TestPointer<uint16_t*>(); 1.242 + TestPointer<uint32_t*>(); 1.243 + TestEnum(); 1.244 + TestBool(); 1.245 +}