xref: /openbsd-src/gnu/llvm/compiler-rt/lib/sanitizer_common/tests/sanitizer_atomic_test.cpp (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
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