Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: crosstest/test_sync_atomic_main.cpp

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

Powered by Google App Engine
This is Rietveld 408576698