1 //===-- sanitizer_atomic_test.cpp -----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_atomic.h"
13 #include "gtest/gtest.h"
15 #ifndef __has_extension
16 #define __has_extension(x) 0
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
25 # error Unsupported compiler.
29 namespace __sanitizer
{
33 typename
T::Type magic0
;
35 typename
T::Type magic1
;
37 static ValAndMagic
<T
> *sink
;
41 ValAndMagic
<T
> *ValAndMagic
<T
>::sink
;
43 template<typename T
, memory_order load_mo
, memory_order store_mo
>
44 void CheckStoreLoad() {
45 typedef typename
T::Type Type
;
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.
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
);
63 EXPECT_EQ(val
.magic0
, (Type
)-3);
64 EXPECT_EQ(val
.magic1
, (Type
)-3);
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
>();
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
>();
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
>();
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
>();
96 CheckStoreLoad
<atomic_uintptr_t
, memory_order_relaxed
, memory_order_relaxed
>
98 CheckStoreLoad
<atomic_uintptr_t
, memory_order_consume
, memory_order_relaxed
>
100 CheckStoreLoad
<atomic_uintptr_t
, memory_order_acquire
, memory_order_relaxed
>
102 CheckStoreLoad
<atomic_uintptr_t
, memory_order_relaxed
, memory_order_release
>
104 CheckStoreLoad
<atomic_uintptr_t
, memory_order_seq_cst
, memory_order_seq_cst
>
108 // Clang crashes while compiling this test for Android:
109 // http://llvm.org/bugs/show_bug.cgi?id=15587
110 #if !SANITIZER_ANDROID
112 void CheckAtomicCompareExchange() {
113 typedef typename
T::Type Type
;
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
);
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
);
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
>();
143 CheckAtomicCompareExchange
<atomic_uintptr_t
>();
145 #endif //!SANITIZER_ANDROID
147 } // namespace __sanitizer