/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/Assertions.h" #include "mozilla/Atomics.h" #include <stdint.h> using mozilla::Atomic; using mozilla::MemoryOrdering; using mozilla::Relaxed; using mozilla::ReleaseAcquire; using mozilla::SequentiallyConsistent; #define A(a,b) MOZ_RELEASE_ASSERT(a,b) template <typename T, MemoryOrdering Order> static void TestTypeWithOrdering() { Atomic<T, Order> atomic(5); A(atomic == 5, "Atomic variable did not initialize"); // Test atomic increment A(++atomic == T(6), "Atomic increment did not work"); A(atomic++ == T(6), "Atomic post-increment did not work"); A(atomic == T(7), "Atomic post-increment did not work"); // Test atomic decrement A(--atomic == 6, "Atomic decrement did not work"); A(atomic-- == 6, "Atomic post-decrement did not work"); A(atomic == 5, "Atomic post-decrement did not work"); // Test other arithmetic. T result; result = (atomic += T(5)); A(atomic == T(10), "Atomic += did not work"); A(result == T(10), "Atomic += returned the wrong value"); result = (atomic -= T(3)); A(atomic == T(7), "Atomic -= did not work"); A(result == T(7), "Atomic -= returned the wrong value"); // Test assignment result = (atomic = T(5)); A(atomic == T(5), "Atomic assignment failed"); A(result == T(5), "Atomic assignment returned the wrong value"); // Test logical operations. result = (atomic ^= T(2)); A(atomic == T(7), "Atomic ^= did not work"); A(result == T(7), "Atomic ^= returned the wrong value"); result = (atomic ^= T(4)); A(atomic == T(3), "Atomic ^= did not work"); A(result == T(3), "Atomic ^= returned the wrong value"); result = (atomic |= T(8)); A(atomic == T(11), "Atomic |= did not work"); A(result == T(11), "Atomic |= returned the wrong value"); result = (atomic |= T(8)); A(atomic == T(11), "Atomic |= did not work"); A(result == T(11), "Atomic |= returned the wrong value"); result = (atomic &= T(12)); A(atomic == T(8), "Atomic &= did not work"); A(result == T(8), "Atomic &= returned the wrong value"); // Test exchange. atomic = T(30); result = atomic.exchange(42); A(atomic == T(42), "Atomic exchange did not work"); A(result == T(30), "Atomic exchange returned the wrong value"); // Test CAS. atomic = T(1); bool boolResult = atomic.compareExchange(0, 2); A(!boolResult, "CAS should have returned false."); A(atomic == T(1), "CAS shouldn't have done anything."); boolResult = atomic.compareExchange(1, 42); A(boolResult, "CAS should have succeeded."); A(atomic == T(42), "CAS should have changed atomic's value."); } template<typename T, MemoryOrdering Order> static void TestPointerWithOrdering() { T array1[10]; Atomic<T*, Order> atomic(array1); A(atomic == array1, "Atomic variable did not initialize"); // Test atomic increment A(++atomic == array1 + 1, "Atomic increment did not work"); A(atomic++ == array1 + 1, "Atomic post-increment did not work"); A(atomic == array1 + 2, "Atomic post-increment did not work"); // Test atomic decrement A(--atomic == array1 + 1, "Atomic decrement did not work"); A(atomic-- == array1 + 1, "Atomic post-decrement did not work"); A(atomic == array1, "Atomic post-decrement did not work"); // Test other arithmetic operations T* result; result = (atomic += 2); A(atomic == array1 + 2, "Atomic += did not work"); A(result == array1 + 2, "Atomic += returned the wrong value"); result = (atomic -= 1); A(atomic == array1 + 1, "Atomic -= did not work"); A(result == array1 + 1, "Atomic -= returned the wrong value"); // Test stores result = (atomic = array1); A(atomic == array1, "Atomic assignment did not work"); A(result == array1, "Atomic assignment returned the wrong value"); // Test exchange atomic = array1 + 2; result = atomic.exchange(array1); A(atomic == array1, "Atomic exchange did not work"); A(result == array1 + 2, "Atomic exchange returned the wrong value"); atomic = array1; bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2); A(!boolResult, "CAS should have returned false."); A(atomic == array1, "CAS shouldn't have done anything."); boolResult = atomic.compareExchange(array1, array1 + 3); A(boolResult, "CAS should have succeeded."); A(atomic == array1 + 3, "CAS should have changed atomic's value."); } enum EnumType { EnumType_0 = 0, EnumType_1 = 1, EnumType_2 = 2, EnumType_3 = 3 }; template<MemoryOrdering Order> static void TestEnumWithOrdering() { Atomic<EnumType, Order> atomic(EnumType_2); A(atomic == EnumType_2, "Atomic variable did not initialize"); // Test assignment EnumType result; result = (atomic = EnumType_3); A(atomic == EnumType_3, "Atomic assignment failed"); A(result == EnumType_3, "Atomic assignment returned the wrong value"); // Test exchange. atomic = EnumType_1; result = atomic.exchange(EnumType_2); A(atomic == EnumType_2, "Atomic exchange did not work"); A(result == EnumType_1, "Atomic exchange returned the wrong value"); // Test CAS. atomic = EnumType_1; bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2); A(!boolResult, "CAS should have returned false."); A(atomic == EnumType_1, "CAS shouldn't have done anything."); boolResult = atomic.compareExchange(EnumType_1, EnumType_3); A(boolResult, "CAS should have succeeded."); A(atomic == EnumType_3, "CAS should have changed atomic's value."); } enum class EnumClass : uint32_t { Value0 = 0, Value1 = 1, Value2 = 2, Value3 = 3 }; template<MemoryOrdering Order> static void TestEnumClassWithOrdering() { Atomic<EnumClass, Order> atomic(EnumClass::Value2); A(atomic == EnumClass::Value2, "Atomic variable did not initialize"); // Test assignment EnumClass result; result = (atomic = EnumClass::Value3); A(atomic == EnumClass::Value3, "Atomic assignment failed"); A(result == EnumClass::Value3, "Atomic assignment returned the wrong value"); // Test exchange. atomic = EnumClass::Value1; result = atomic.exchange(EnumClass::Value2); A(atomic == EnumClass::Value2, "Atomic exchange did not work"); A(result == EnumClass::Value1, "Atomic exchange returned the wrong value"); // Test CAS. atomic = EnumClass::Value1; bool boolResult = atomic.compareExchange(EnumClass::Value0, EnumClass::Value2); A(!boolResult, "CAS should have returned false."); A(atomic == EnumClass::Value1, "CAS shouldn't have done anything."); boolResult = atomic.compareExchange(EnumClass::Value1, EnumClass::Value3); A(boolResult, "CAS should have succeeded."); A(atomic == EnumClass::Value3, "CAS should have changed atomic's value."); } template <MemoryOrdering Order> static void TestBoolWithOrdering() { Atomic<bool, Order> atomic(false); A(atomic == false, "Atomic variable did not initialize"); // Test assignment bool result; result = (atomic = true); A(atomic == true, "Atomic assignment failed"); A(result == true, "Atomic assignment returned the wrong value"); // Test exchange. atomic = false; result = atomic.exchange(true); A(atomic == true, "Atomic exchange did not work"); A(result == false, "Atomic exchange returned the wrong value"); // Test CAS. atomic = false; bool boolResult = atomic.compareExchange(true, false); A(!boolResult, "CAS should have returned false."); A(atomic == false, "CAS shouldn't have done anything."); boolResult = atomic.compareExchange(false, true); A(boolResult, "CAS should have succeeded."); A(atomic == true, "CAS should have changed atomic's value."); } template <typename T> static void TestType() { TestTypeWithOrdering<T, SequentiallyConsistent>(); TestTypeWithOrdering<T, ReleaseAcquire>(); TestTypeWithOrdering<T, Relaxed>(); } template<typename T> static void TestPointer() { TestPointerWithOrdering<T, SequentiallyConsistent>(); TestPointerWithOrdering<T, ReleaseAcquire>(); TestPointerWithOrdering<T, Relaxed>(); } static void TestEnum() { TestEnumWithOrdering<SequentiallyConsistent>(); TestEnumWithOrdering<ReleaseAcquire>(); TestEnumWithOrdering<Relaxed>(); TestEnumClassWithOrdering<SequentiallyConsistent>(); TestEnumClassWithOrdering<ReleaseAcquire>(); TestEnumClassWithOrdering<Relaxed>(); } static void TestBool() { TestBoolWithOrdering<SequentiallyConsistent>(); TestBoolWithOrdering<ReleaseAcquire>(); TestBoolWithOrdering<Relaxed>(); } #undef A int main() { TestType<uint32_t>(); TestType<int32_t>(); TestType<uint64_t>(); TestType<int64_t>(); TestType<intptr_t>(); TestType<uintptr_t>(); TestPointer<int>(); TestPointer<float>(); TestPointer<uint16_t*>(); TestPointer<uint32_t*>(); TestEnum(); TestBool(); return 0; }