1 //===-- sanitizer_atomic_test.cc ------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "sanitizer_common/sanitizer_atomic.h" 14 #include "gtest/gtest.h" 15 16 namespace __sanitizer { 17 18 template<typename T> 19 struct ValAndMagic { 20 typename T::Type magic0; 21 T a; 22 typename T::Type magic1; 23 24 static ValAndMagic<T> *sink; 25 }; 26 27 template<typename T> 28 ValAndMagic<T> *ValAndMagic<T>::sink; 29 30 template<typename T, memory_order load_mo, memory_order store_mo> 31 void CheckStoreLoad() { 32 typedef typename T::Type Type; 33 ValAndMagic<T> val; 34 // Prevent the compiler from scalarizing the struct. 35 ValAndMagic<T>::sink = &val; 36 // Ensure that surrounding memory is not overwritten. 37 val.magic0 = val.magic1 = (Type)-3; 38 for (u64 i = 0; i < 100; i++) { 39 // Generate a value that occupies all bytes of the variable. 40 u64 v = i; 41 v |= v << 8; 42 v |= v << 16; 43 v |= v << 32; 44 val.a.val_dont_use = (Type)v; 45 EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v); 46 val.a.val_dont_use = (Type)-1; 47 atomic_store(&val.a, (Type)v, store_mo); 48 EXPECT_EQ(val.a.val_dont_use, (Type)v); 49 } 50 EXPECT_EQ(val.magic0, (Type)-3); 51 EXPECT_EQ(val.magic1, (Type)-3); 52 } 53 54 TEST(SanitizerCommon, AtomicStoreLoad) { 55 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>(); 56 CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>(); 57 CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>(); 58 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>(); 59 CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>(); 60 61 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>(); 62 CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>(); 63 CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>(); 64 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>(); 65 CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>(); 66 67 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>(); 68 CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>(); 69 CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>(); 70 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>(); 71 CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>(); 72 73 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>(); 74 CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>(); 75 CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>(); 76 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>(); 77 CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>(); 78 79 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed> 80 (); 81 CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed> 82 (); 83 CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed> 84 (); 85 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release> 86 (); 87 CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst> 88 (); 89 } 90 91 // Clang crashes while compiling this test for Android: 92 // http://llvm.org/bugs/show_bug.cgi?id=15587 93 #if !SANITIZER_ANDROID 94 template<typename T> 95 void CheckAtomicCompareExchange() { 96 typedef typename T::Type Type; 97 { 98 Type old_val = 42; 99 Type new_val = 24; 100 Type var = old_val; 101 EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, 102 memory_order_relaxed)); 103 EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, 104 memory_order_relaxed)); 105 EXPECT_EQ(new_val, old_val); 106 } 107 { 108 Type old_val = 42; 109 Type new_val = 24; 110 Type var = old_val; 111 EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, 112 memory_order_relaxed)); 113 EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, 114 memory_order_relaxed)); 115 EXPECT_EQ(new_val, old_val); 116 } 117 } 118 119 TEST(SanitizerCommon, AtomicCompareExchangeTest) { 120 CheckAtomicCompareExchange<atomic_uint8_t>(); 121 CheckAtomicCompareExchange<atomic_uint16_t>(); 122 CheckAtomicCompareExchange<atomic_uint32_t>(); 123 CheckAtomicCompareExchange<atomic_uint64_t>(); 124 CheckAtomicCompareExchange<atomic_uintptr_t>(); 125 } 126 #endif //!SANITIZER_ANDROID 127 128 } // namespace __sanitizer 129