1 //===-- sanitizer_atomic_test.cpp -----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime. 10 // 11 //===----------------------------------------------------------------------===// 12 #include "sanitizer_common/sanitizer_atomic.h" 13 #include "gtest/gtest.h" 14 15 #ifndef __has_extension 16 #define __has_extension(x) 0 17 #endif 18 19 #ifndef ATOMIC_LLONG_LOCK_FREE 20 # if __has_extension(c_atomic) || __has_extension(cxx_atomic) 21 # define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE 22 # elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) 23 # define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE 24 # else 25 # error Unsupported compiler. 26 # endif 27 #endif 28 29 namespace __sanitizer { 30 31 template<typename T> 32 struct ValAndMagic { 33 typename T::Type magic0; 34 T a; 35 typename T::Type magic1; 36 37 static ValAndMagic<T> *sink; 38 }; 39 40 template<typename T> 41 ValAndMagic<T> *ValAndMagic<T>::sink; 42 43 template<typename T, memory_order load_mo, memory_order store_mo> 44 void CheckStoreLoad() { 45 typedef typename T::Type Type; 46 ValAndMagic<T> val; 47 // Prevent the compiler from scalarizing the struct. 48 ValAndMagic<T>::sink = &val; 49 // Ensure that surrounding memory is not overwritten. 50 val.magic0 = val.magic1 = (Type)-3; 51 for (u64 i = 0; i < 100; i++) { 52 // Generate a value that occupies all bytes of the variable. 53 u64 v = i; 54 v |= v << 8; 55 v |= v << 16; 56 v |= v << 32; 57 val.a.val_dont_use = (Type)v; 58 EXPECT_EQ(atomic_load(&val.a, load_mo), (Type)v); 59 val.a.val_dont_use = (Type)-1; 60 atomic_store(&val.a, (Type)v, store_mo); 61 EXPECT_EQ(val.a.val_dont_use, (Type)v); 62 } 63 EXPECT_EQ(val.magic0, (Type)-3); 64 EXPECT_EQ(val.magic1, (Type)-3); 65 } 66 67 TEST(SanitizerCommon, AtomicStoreLoad) { 68 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_relaxed>(); 69 CheckStoreLoad<atomic_uint8_t, memory_order_consume, memory_order_relaxed>(); 70 CheckStoreLoad<atomic_uint8_t, memory_order_acquire, memory_order_relaxed>(); 71 CheckStoreLoad<atomic_uint8_t, memory_order_relaxed, memory_order_release>(); 72 CheckStoreLoad<atomic_uint8_t, memory_order_seq_cst, memory_order_seq_cst>(); 73 74 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_relaxed>(); 75 CheckStoreLoad<atomic_uint16_t, memory_order_consume, memory_order_relaxed>(); 76 CheckStoreLoad<atomic_uint16_t, memory_order_acquire, memory_order_relaxed>(); 77 CheckStoreLoad<atomic_uint16_t, memory_order_relaxed, memory_order_release>(); 78 CheckStoreLoad<atomic_uint16_t, memory_order_seq_cst, memory_order_seq_cst>(); 79 80 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_relaxed>(); 81 CheckStoreLoad<atomic_uint32_t, memory_order_consume, memory_order_relaxed>(); 82 CheckStoreLoad<atomic_uint32_t, memory_order_acquire, memory_order_relaxed>(); 83 CheckStoreLoad<atomic_uint32_t, memory_order_relaxed, memory_order_release>(); 84 CheckStoreLoad<atomic_uint32_t, memory_order_seq_cst, memory_order_seq_cst>(); 85 86 // Avoid fallbacking to software emulated compiler atomics, that are usually 87 // provided by libatomic, which is not always present. 88 #if ATOMIC_LLONG_LOCK_FREE == 2 89 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_relaxed>(); 90 CheckStoreLoad<atomic_uint64_t, memory_order_consume, memory_order_relaxed>(); 91 CheckStoreLoad<atomic_uint64_t, memory_order_acquire, memory_order_relaxed>(); 92 CheckStoreLoad<atomic_uint64_t, memory_order_relaxed, memory_order_release>(); 93 CheckStoreLoad<atomic_uint64_t, memory_order_seq_cst, memory_order_seq_cst>(); 94 #endif 95 96 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_relaxed> 97 (); 98 CheckStoreLoad<atomic_uintptr_t, memory_order_consume, memory_order_relaxed> 99 (); 100 CheckStoreLoad<atomic_uintptr_t, memory_order_acquire, memory_order_relaxed> 101 (); 102 CheckStoreLoad<atomic_uintptr_t, memory_order_relaxed, memory_order_release> 103 (); 104 CheckStoreLoad<atomic_uintptr_t, memory_order_seq_cst, memory_order_seq_cst> 105 (); 106 } 107 108 // Clang crashes while compiling this test for Android: 109 // http://llvm.org/bugs/show_bug.cgi?id=15587 110 #if !SANITIZER_ANDROID 111 template<typename T> 112 void CheckAtomicCompareExchange() { 113 typedef typename T::Type Type; 114 { 115 Type old_val = 42; 116 Type new_val = 24; 117 Type var = old_val; 118 EXPECT_TRUE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, 119 memory_order_relaxed)); 120 EXPECT_FALSE(atomic_compare_exchange_strong((T*)&var, &old_val, new_val, 121 memory_order_relaxed)); 122 EXPECT_EQ(new_val, old_val); 123 } 124 { 125 Type old_val = 42; 126 Type new_val = 24; 127 Type var = old_val; 128 EXPECT_TRUE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, 129 memory_order_relaxed)); 130 EXPECT_FALSE(atomic_compare_exchange_weak((T*)&var, &old_val, new_val, 131 memory_order_relaxed)); 132 EXPECT_EQ(new_val, old_val); 133 } 134 } 135 136 TEST(SanitizerCommon, AtomicCompareExchangeTest) { 137 CheckAtomicCompareExchange<atomic_uint8_t>(); 138 CheckAtomicCompareExchange<atomic_uint16_t>(); 139 CheckAtomicCompareExchange<atomic_uint32_t>(); 140 #if ATOMIC_LLONG_LOCK_FREE == 2 141 CheckAtomicCompareExchange<atomic_uint64_t>(); 142 #endif 143 CheckAtomicCompareExchange<atomic_uintptr_t>(); 144 } 145 #endif //!SANITIZER_ANDROID 146 147 } // namespace __sanitizer 148