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