OLD | NEW |
---|---|
(Empty) | |
1 /* crosstest.py --test=test_sync_atomic.cpp --driver=test_sync_atomic_main.cpp \ | |
2 --prefix=Subzero_ --output=test_sync_atomic */ | |
Jim Stichnoth
2014/07/08 04:50:19
Add --crosstest-bitcode=0 ?
jvoung (off chromium)
2014/07/08 18:14:06
Done.
| |
3 | |
4 #include <pthread.h> | |
5 #include <stdint.h> | |
6 | |
7 #include <cstdlib> | |
8 #include <iostream> | |
9 | |
10 // Include test_sync_atomic.h twice - once normally, and once within the | |
11 // Subzero_ namespace, corresponding to the llc and Subzero translated | |
12 // object files, respectively. | |
13 #include "test_sync_atomic.h" | |
14 namespace Subzero_ { | |
15 #include "test_sync_atomic.h" | |
16 } | |
17 | |
18 volatile uint64_t Values[] = { | |
19 0, 1, 0x7e, | |
20 0x7f, 0x80, 0x81, | |
21 0xfe, 0xff, 0x7ffe, | |
22 0x7fff, 0x8000, 0x8001, | |
23 0xfffe, 0xffff, | |
24 0x007fffff /*Max subnormal + */, | |
25 0x00800000 /*Min+ */, 0x7f7fffff /*Max+ */, | |
26 0x7f800000 /*+Inf*/, 0xff800000 /*-Inf*/, | |
27 0x7fa00000 /*SNaN*/, 0x7fc00000 /*QNaN*/, | |
28 0x7ffffffe, 0x7fffffff, 0x80000000, | |
29 0x80000001, 0xfffffffe, 0xffffffff, | |
30 0x100000000ll, 0x100000001ll, | |
31 0x000fffffffffffffll /*Max subnormal + */, | |
32 0x0010000000000000ll /*Min+ */, | |
33 0x7fefffffffffffffll /*Max+ */, | |
34 0x7ff0000000000000ll /*+Inf*/, | |
35 0xfff0000000000000ll /*-Inf*/, | |
36 0x7ff0000000000001ll /*SNaN*/, | |
37 0x7ff8000000000000ll /*QNaN*/, | |
38 0x7ffffffffffffffell, 0x7fffffffffffffffll, 0x8000000000000000ll, | |
39 0x8000000000000001ll, 0xfffffffffffffffell, 0xffffffffffffffffll }; | |
40 | |
41 const static size_t NumValues = sizeof(Values) / sizeof(*Values); | |
42 | |
43 struct AtomicLocs { | |
Jim Stichnoth
2014/07/08 04:50:19
Maybe change to:
struct { ... } AtomicLocs;
sinc
jvoung (off chromium)
2014/07/08 18:14:06
Done.
| |
44 volatile uint8_t l8; | |
45 volatile uint16_t l16; | |
46 volatile uint32_t l32; | |
47 volatile uint64_t l64; | |
48 }; | |
49 | |
50 AtomicLocs AtomicLocs; | |
51 | |
52 template <typename Type> | |
53 void testAtomicRMW(volatile Type *AtomicLoc, | |
54 size_t &TotalTests, size_t &Passes, size_t &Failures) { | |
55 typedef Type (*FuncType)(bool, volatile Type*, Type); | |
56 static struct { | |
57 const char *Name; | |
58 FuncType FuncLlc; | |
59 FuncType FuncSz; | |
60 } Funcs[] = { | |
61 #define X(inst) \ | |
62 { \ | |
63 STR(inst), test_##inst, Subzero_::test_##inst \ | |
64 }, \ | |
65 { \ | |
66 STR(inst) "_alloca", test_alloca_##inst, Subzero_::test_alloca_##inst \ | |
67 }, \ | |
68 { \ | |
69 STR(inst) "_const", test_const_##inst, Subzero_::test_const_##inst \ | |
70 } \ | |
Jim Stichnoth
2014/07/08 04:50:19
Put comma on the same line, as above?
jvoung (off chromium)
2014/07/08 18:14:07
Done.
| |
71 , | |
72 RMWOP_TABLE | |
73 #undef X | |
74 }; | |
75 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | |
76 | |
77 for (size_t f = 0; f < NumFuncs; ++f) { | |
78 for (size_t i = 0; i < NumValues; ++i) { | |
79 Type Value1 = static_cast<Type>(Values[i]); | |
80 for (size_t j = 0; j < NumValues; ++j) { | |
81 Type Value2 = static_cast<Type>(Values[j]); | |
82 for (size_t k = 0; k < 2; ++k) { | |
83 bool fetch_first = k; | |
84 ++TotalTests; | |
85 *AtomicLoc = Value1; | |
86 Type ResultSz1 = Funcs[f].FuncSz( | |
87 fetch_first, AtomicLoc, Value2); | |
88 Type ResultSz2 = *AtomicLoc; | |
89 *AtomicLoc = Value1; | |
90 Type ResultLlc1 = Funcs[f].FuncLlc( | |
91 fetch_first, AtomicLoc, Value2); | |
92 Type ResultLlc2 = *AtomicLoc; | |
93 if (ResultSz1 == ResultLlc1 && ResultSz2 == ResultLlc2) { | |
94 ++Passes; | |
95 } else { | |
96 ++Failures; | |
97 std::cout << "test_" << Funcs[f].Name | |
98 << (8 * sizeof(Type)) << "(" | |
99 << static_cast<uint64_t>(Value1) << ", " | |
100 << static_cast<uint64_t>(Value2) | |
101 << "): sz1=" << static_cast<uint64_t>(ResultSz1) | |
102 << " llc1=" << static_cast<uint64_t>(ResultLlc1) | |
103 << " sz2=" << static_cast<uint64_t>(ResultSz2) | |
104 << " llc2=" << static_cast<uint64_t>(ResultLlc2) | |
105 << std::endl; | |
106 } | |
107 } | |
108 } | |
109 } | |
110 } | |
111 } | |
112 | |
113 template <typename Type> | |
114 void testValCompareAndSwap(volatile Type *AtomicLoc, size_t &TotalTests, | |
115 size_t &Passes, size_t &Failures) { | |
116 for (size_t i = 0; i < NumValues; ++i) { | |
117 Type Value1 = static_cast<Type>(Values[i]); | |
118 for (size_t j = 0; j < NumValues; ++j) { | |
119 Type Value2 = static_cast<Type>(Values[j]); | |
120 for (size_t f = 0; f < 2; ++f) { | |
121 bool flip = f; | |
122 ++TotalTests; | |
123 *AtomicLoc = Value1; | |
124 Type ResultSz1 = Subzero_::test_val_cmp_swap( | |
125 AtomicLoc, flip ? Value2 : Value1, Value2); | |
126 Type ResultSz2 = *AtomicLoc; | |
127 *AtomicLoc = Value1; | |
128 Type ResultLlc1 = test_val_cmp_swap( | |
129 AtomicLoc, flip ? Value2 : Value1, Value2); | |
130 Type ResultLlc2 = *AtomicLoc; | |
131 if (ResultSz1 == ResultLlc1 && ResultSz2 == ResultLlc2) { | |
132 ++Passes; | |
133 } else { | |
134 ++Failures; | |
135 std::cout << "test_val_cmp_swap" << (8 * sizeof(Type)) << "(" | |
136 << static_cast<uint64_t>(Value1) << ", " | |
137 << static_cast<uint64_t>(Value2) | |
138 << "): sz1=" << static_cast<uint64_t>(ResultSz1) | |
139 << " llc1=" << static_cast<uint64_t>(ResultLlc1) | |
140 << " sz2=" << static_cast<uint64_t>(ResultSz2) | |
141 << " llc2=" << static_cast<uint64_t>(ResultLlc2) | |
142 << std::endl; | |
143 } | |
144 } | |
145 } | |
146 } | |
147 } | |
148 | |
149 template <typename Type> | |
150 struct ThreadData { | |
151 Type (*FuncPtr)(bool, volatile Type*, Type); | |
152 bool Fetch; | |
153 volatile Type *Ptr; | |
154 Type Adjustment; | |
155 }; | |
156 | |
157 template <typename Type> | |
158 void *threadWrapper(void *Data) { | |
159 const size_t NumReps = 8000; | |
160 ThreadData<Type> *TData = reinterpret_cast<ThreadData<Type>*>(Data); | |
161 for (size_t i = 0; i < NumReps; ++i) { | |
162 (void)TData->FuncPtr(TData->Fetch, TData->Ptr, TData->Adjustment); | |
163 } | |
164 return NULL; | |
165 } | |
166 | |
167 template <typename Type> | |
168 void testAtomicRMWThreads(volatile Type *AtomicLoc, size_t &TotalTests, | |
169 size_t &Passes, size_t &Failures) { | |
170 typedef Type (*FuncType)(bool, volatile Type*, Type); | |
171 static struct { | |
172 const char *Name; | |
173 FuncType FuncLlc; | |
174 FuncType FuncSz; | |
175 } Funcs[] = { | |
176 #define X(inst) \ | |
177 { \ | |
178 STR(inst), test_##inst, Subzero_::test_##inst \ | |
179 }, \ | |
180 { \ | |
181 STR(inst) "_alloca", test_alloca_##inst, Subzero_::test_alloca_##inst \ | |
182 }, | |
183 RMWOP_TABLE | |
184 #undef X | |
185 }; | |
186 const static size_t NumFuncs = sizeof(Funcs) / sizeof(*Funcs); | |
187 | |
188 // Just test a few values, otherwise it takes a *really* long time. | |
189 volatile uint64_t ValuesSubset[] = { 1, 0x7e, 0x80 }; | |
190 const size_t NumValuesSubset = sizeof(ValuesSubset) / sizeof(*ValuesSubset); | |
191 | |
192 for (size_t f = 0; f < NumFuncs; ++f) { | |
193 for (size_t i = 0; i < NumValuesSubset; ++i) { | |
194 Type Value1 = static_cast<Type>(ValuesSubset[i]); | |
195 for (size_t j = 0; j < NumValuesSubset; ++j) { | |
196 Type Value2 = static_cast<Type>(ValuesSubset[j]); | |
197 bool fetch_first = true; | |
198 ThreadData<Type> TDataSz = { | |
199 Funcs[f].FuncSz, fetch_first, AtomicLoc, Value2 }; | |
200 ThreadData<Type> TDataLlc = { | |
201 Funcs[f].FuncLlc, fetch_first, AtomicLoc, Value2 }; | |
202 ++TotalTests; | |
203 const size_t num_threads = 4; | |
204 pthread_t t[num_threads]; | |
205 | |
206 // Try N threads w/ just Llc. | |
207 *AtomicLoc = Value1; | |
208 for (size_t m = 0; m < num_threads; ++m) { | |
209 pthread_create(&t[m], NULL, &threadWrapper<Type>, | |
210 reinterpret_cast<void *>(&TDataLlc)); | |
211 } | |
212 for (size_t m = 0; m < num_threads; ++m) { | |
213 pthread_join(t[m], NULL); | |
214 } | |
215 Type ResultLlc = *AtomicLoc; | |
216 | |
217 // Try N threads w/ both Sz and Llc. | |
218 *AtomicLoc = Value1; | |
219 for (size_t m = 0; m < num_threads; ++m) { | |
220 pthread_create(&t[m], NULL, &threadWrapper<Type>, | |
221 m % 2 == 0 | |
222 ? reinterpret_cast<void *>(&TDataLlc) | |
223 : reinterpret_cast<void *>(&TDataSz)); | |
224 } | |
225 for (size_t m = 0; m < num_threads; ++m) { | |
226 pthread_join(t[m], NULL); | |
227 } | |
228 Type ResultMixed = *AtomicLoc; | |
229 | |
230 if (ResultLlc == ResultMixed) { | |
231 ++Passes; | |
232 } else { | |
233 ++Failures; | |
234 std::cout << "test_with_threads_" << Funcs[f].Name | |
235 << (8 * sizeof(Type)) << "(" | |
236 << static_cast<uint64_t>(Value1) << ", " | |
237 << static_cast<uint64_t>(Value2) | |
238 << "): llc=" << static_cast<uint64_t>(ResultLlc) | |
239 << " mixed=" << static_cast<uint64_t>(ResultMixed) | |
240 << std::endl; | |
241 } | |
242 } | |
243 } | |
244 } | |
245 } | |
246 | |
247 int main(int argc, char **argv) { | |
248 size_t TotalTests = 0; | |
249 size_t Passes = 0; | |
250 size_t Failures = 0; | |
251 | |
252 testAtomicRMW<uint8_t>(&AtomicLocs.l8, TotalTests, Passes, Failures); | |
253 testAtomicRMW<uint16_t>(&AtomicLocs.l16, TotalTests, Passes, Failures); | |
254 testAtomicRMW<uint32_t>(&AtomicLocs.l32, TotalTests, Passes, Failures); | |
255 testAtomicRMW<uint64_t>(&AtomicLocs.l64, TotalTests, Passes, Failures); | |
256 testValCompareAndSwap<uint8_t>( | |
257 &AtomicLocs.l8, TotalTests, Passes, Failures); | |
258 testValCompareAndSwap<uint16_t>( | |
259 &AtomicLocs.l16, TotalTests, Passes, Failures); | |
260 testValCompareAndSwap<uint32_t>( | |
261 &AtomicLocs.l32, TotalTests, Passes, Failures); | |
262 testValCompareAndSwap<uint64_t>( | |
263 &AtomicLocs.l64, TotalTests, Passes, Failures); | |
264 testAtomicRMWThreads<uint8_t>( | |
265 &AtomicLocs.l8, TotalTests, Passes, Failures); | |
266 testAtomicRMWThreads<uint16_t>( | |
267 &AtomicLocs.l16, TotalTests, Passes, Failures); | |
268 testAtomicRMWThreads<uint32_t>( | |
269 &AtomicLocs.l32, TotalTests, Passes, Failures); | |
270 testAtomicRMWThreads<uint64_t>( | |
271 &AtomicLocs.l64, TotalTests, Passes, Failures); | |
272 | |
273 std::cout << "TotalTests=" << TotalTests << " Passes=" << Passes | |
274 << " Failures=" << Failures << "\n"; | |
275 return Failures; | |
276 } | |
OLD | NEW |