diff options
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp')
-rw-r--r-- | compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp new file mode 100644 index 00000000000..9a3078b25d7 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp @@ -0,0 +1,127 @@ +//===-- sanitizer_atomic_test.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// +//===----------------------------------------------------------------------===// +#include "sanitizer_common/sanitizer_atomic.h" +#include "gtest/gtest.h" + +namespace __sanitizer { + +template<typename T> +struct ValAndMagic { + typename T::Type magic0; + T a; + typename T::Type magic1; + + static ValAndMagic<T> *sink; +}; + +template<typename T> +ValAndMagic<T> *ValAndMagic<T>::sink; + +template<typename T, memory_order load_mo, memory_order store_mo> +void CheckStoreLoad() { + typedef typename T::Type Type; + ValAndMagic<T> val; + // Prevent the compiler from scalarizing the struct. + ValAndMagic<T>::sink = &val; + // Ensure that surrounding memory is not overwritten. + val.magic0 = val.magic1 = (Type)-3; + for (u64 i = 0; i < 100; i++) { + // Generate a value that occupies all bytes of the variable. + u64 v = i; + v |= v << 8; + v |= v << 16; + v |= v << 32; + val.a.val_dont_use = (Type)v; + EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v); + val.a.val_dont_use = (Type)-1; + atomic_store(&val.a, (Type)v, store_mo); + EXPECT_EQ(val.a.val_dont_use, (Type)v); + } + EXPECT_EQ(val.magic0, (Type)-3); + EXPECT_EQ(val.magic1, (Type)-3); +} + +TEST(SanitizerCommon, AtomicStoreLoad) { + CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>(); + CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>(); + + CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>(); + CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>(); + + CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>(); + CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>(); + + CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>(); + CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>(); + CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>(); + + CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed> + (); + CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed> + (); + CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed> + (); + CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release> + (); + CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst> + (); +} + +// Clang crashes while compiling this test for Android: +// http://llvm.org/bugs/show_bug.cgi?id=15587 +#if !SANITIZER_ANDROID +template<typename T> +void CheckAtomicCompareExchange() { + typedef typename T::Type Type; + { + Type old_val = 42; + Type new_val = 24; + Type var = old_val; + EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, + memory_order_relaxed)); + EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, + memory_order_relaxed)); + EXPECT_EQ(new_val, old_val); + } + { + Type old_val = 42; + Type new_val = 24; + Type var = old_val; + EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, + memory_order_relaxed)); + EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, + memory_order_relaxed)); + EXPECT_EQ(new_val, old_val); + } +} + +TEST(SanitizerCommon, AtomicCompareExchangeTest) { + CheckAtomicCompareExchange<atomic_uint8_t>(); + CheckAtomicCompareExchange<atomic_uint16_t>(); + CheckAtomicCompareExchange<atomic_uint32_t>(); + CheckAtomicCompareExchange<atomic_uint64_t>(); + CheckAtomicCompareExchange<atomic_uintptr_t>(); +} +#endif //!SANITIZER_ANDROID + +} // namespace __sanitizer |