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