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