//===-- sanitizer_atomic_test.cc ------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file is a part of ThreadSanitizer/AddressSanitizer runtime. // //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_atomic.h" #include "gtest/gtest.h" namespace __sanitizer { template struct ValAndMagic { typename T::Type magic0; T a; typename T::Type magic1; static ValAndMagic *sink; }; template ValAndMagic *ValAndMagic::sink; template void CheckStoreLoad() { typedef typename T::Type Type; ValAndMagic val; // Prevent the compiler from scalarizing the struct. ValAndMagic::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(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad(); CheckStoreLoad (); CheckStoreLoad (); CheckStoreLoad (); CheckStoreLoad (); CheckStoreLoad (); } // Clang crashes while compiling this test for Android: // http://llvm.org/bugs/show_bug.cgi?id=15587 #if !SANITIZER_ANDROID template 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(); CheckAtomicCompareExchange(); CheckAtomicCompareExchange(); CheckAtomicCompareExchange(); CheckAtomicCompareExchange(); } #endif //!SANITIZER_ANDROID } // namespace __sanitizer