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
29namespace __sanitizer {
30
31template<typename T>
32struct ValAndMagic {
33 typename T::Type magic0;
34 T a;
35 typename T::Type magic1;
36
37 static ValAndMagic<T> *sink;
38};
39
40template<typename T>
41ValAndMagic<T> *ValAndMagic<T>::sink;
42
43template<typename T, memory_order load_mo, memory_order store_mo>
44void 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
67TEST(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
111template<typename T>
112void 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
136TEST(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

source code of compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp