OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 using namespace v8::base; | 42 using namespace v8::base; |
43 using namespace v8::internal; | 43 using namespace v8::internal; |
44 | 44 |
45 #define __ masm. | 45 #define __ masm. |
46 | 46 |
47 struct MemoryAccess { | 47 struct MemoryAccess { |
48 enum class Kind { | 48 enum class Kind { |
49 None, | 49 None, |
50 Load, | 50 Load, |
51 LoadExcl, | 51 LoadExcl, |
| 52 LoadAcqExcl, |
52 Store, | 53 Store, |
53 StoreExcl, | 54 StoreExcl, |
| 55 StoreRelExcl, |
54 }; | 56 }; |
55 | 57 |
56 enum class Size { | 58 enum class Size { |
57 Byte, | 59 Byte, |
58 HalfWord, | 60 HalfWord, |
59 Word, | 61 Word, |
60 }; | 62 }; |
61 | 63 |
62 MemoryAccess() : kind(Kind::None) {} | 64 MemoryAccess() : kind(Kind::None) {} |
63 MemoryAccess(Kind kind, Size size, size_t offset, int value = 0) | 65 MemoryAccess(Kind kind, Size size, size_t offset, int value = 0) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 | 104 |
103 case MemoryAccess::Size::Word: | 105 case MemoryAccess::Size::Word: |
104 __ ldr(value_reg, MemOperand(addr_reg)); | 106 __ ldr(value_reg, MemOperand(addr_reg)); |
105 break; | 107 break; |
106 } | 108 } |
107 break; | 109 break; |
108 | 110 |
109 case MemoryAccess::Kind::LoadExcl: | 111 case MemoryAccess::Kind::LoadExcl: |
110 switch (access.size) { | 112 switch (access.size) { |
111 case MemoryAccess::Size::Byte: | 113 case MemoryAccess::Size::Byte: |
| 114 __ ldxrb(value_reg, addr_reg); |
| 115 break; |
| 116 |
| 117 case MemoryAccess::Size::HalfWord: |
| 118 __ ldxrh(value_reg, addr_reg); |
| 119 break; |
| 120 |
| 121 case MemoryAccess::Size::Word: |
| 122 __ ldxr(value_reg, addr_reg); |
| 123 break; |
| 124 } |
| 125 break; |
| 126 |
| 127 case MemoryAccess::Kind::LoadAcqExcl: |
| 128 switch (access.size) { |
| 129 case MemoryAccess::Size::Byte: |
112 __ ldaxrb(value_reg, addr_reg); | 130 __ ldaxrb(value_reg, addr_reg); |
113 break; | 131 break; |
114 | 132 |
115 case MemoryAccess::Size::HalfWord: | 133 case MemoryAccess::Size::HalfWord: |
116 __ ldaxrh(value_reg, addr_reg); | 134 __ ldaxrh(value_reg, addr_reg); |
117 break; | 135 break; |
118 | 136 |
119 case MemoryAccess::Size::Word: | 137 case MemoryAccess::Size::Word: |
120 __ ldaxr(value_reg, addr_reg); | 138 __ ldaxr(value_reg, addr_reg); |
121 break; | 139 break; |
(...skipping 16 matching lines...) Expand all Loading... |
138 __ Mov(value_reg, Operand(access.value)); | 156 __ Mov(value_reg, Operand(access.value)); |
139 __ str(value_reg, MemOperand(addr_reg)); | 157 __ str(value_reg, MemOperand(addr_reg)); |
140 break; | 158 break; |
141 } | 159 } |
142 break; | 160 break; |
143 | 161 |
144 case MemoryAccess::Kind::StoreExcl: | 162 case MemoryAccess::Kind::StoreExcl: |
145 switch (access.size) { | 163 switch (access.size) { |
146 case MemoryAccess::Size::Byte: | 164 case MemoryAccess::Size::Byte: |
147 __ Mov(value_reg, Operand(access.value)); | 165 __ Mov(value_reg, Operand(access.value)); |
| 166 __ stxrb(dest_reg, value_reg, addr_reg); |
| 167 break; |
| 168 |
| 169 case MemoryAccess::Size::HalfWord: |
| 170 __ Mov(value_reg, Operand(access.value)); |
| 171 __ stxrh(dest_reg, value_reg, addr_reg); |
| 172 break; |
| 173 |
| 174 case MemoryAccess::Size::Word: |
| 175 __ Mov(value_reg, Operand(access.value)); |
| 176 __ stxr(dest_reg, value_reg, addr_reg); |
| 177 break; |
| 178 } |
| 179 break; |
| 180 |
| 181 case MemoryAccess::Kind::StoreRelExcl: |
| 182 switch (access.size) { |
| 183 case MemoryAccess::Size::Byte: |
| 184 __ Mov(value_reg, Operand(access.value)); |
148 __ stlxrb(dest_reg, value_reg, addr_reg); | 185 __ stlxrb(dest_reg, value_reg, addr_reg); |
149 break; | 186 break; |
150 | 187 |
151 case MemoryAccess::Size::HalfWord: | 188 case MemoryAccess::Size::HalfWord: |
152 __ Mov(value_reg, Operand(access.value)); | 189 __ Mov(value_reg, Operand(access.value)); |
153 __ stlxrh(dest_reg, value_reg, addr_reg); | 190 __ stlxrh(dest_reg, value_reg, addr_reg); |
154 break; | 191 break; |
155 | 192 |
156 case MemoryAccess::Size::Word: | 193 case MemoryAccess::Size::Word: |
157 __ Mov(value_reg, Operand(access.value)); | 194 __ Mov(value_reg, Operand(access.value)); |
158 __ stlxr(dest_reg, value_reg, addr_reg); | 195 __ stlxr(dest_reg, value_reg, addr_reg); |
159 break; | 196 break; |
160 } | 197 } |
161 break; | 198 break; |
162 } | 199 } |
163 } | 200 } |
164 | 201 |
165 static void AssembleLoadExcl(MacroAssembler* assembler, MemoryAccess access, | 202 static void AssembleLoadExcl(MacroAssembler* assembler, MemoryAccess access, |
166 Register value_reg, Register addr_reg) { | 203 Register value_reg, Register addr_reg) { |
167 DCHECK(access.kind == MemoryAccess::Kind::LoadExcl); | 204 DCHECK((access.kind == MemoryAccess::Kind::LoadExcl) || |
| 205 (access.kind == MemoryAccess::Kind::LoadAcqExcl)); |
168 AssembleMemoryAccess(assembler, access, no_reg, value_reg, addr_reg); | 206 AssembleMemoryAccess(assembler, access, no_reg, value_reg, addr_reg); |
169 } | 207 } |
170 | 208 |
171 static void AssembleStoreExcl(MacroAssembler* assembler, MemoryAccess access, | 209 static void AssembleStoreExcl(MacroAssembler* assembler, MemoryAccess access, |
172 Register dest_reg, Register value_reg, | 210 Register dest_reg, Register value_reg, |
173 Register addr_reg) { | 211 Register addr_reg) { |
174 DCHECK(access.kind == MemoryAccess::Kind::StoreExcl); | 212 DCHECK((access.kind == MemoryAccess::Kind::StoreExcl) || |
| 213 (access.kind == MemoryAccess::Kind::StoreRelExcl)); |
175 AssembleMemoryAccess(assembler, access, dest_reg, value_reg, addr_reg); | 214 AssembleMemoryAccess(assembler, access, dest_reg, value_reg, addr_reg); |
176 } | 215 } |
177 | 216 |
178 static void TestInvalidateExclusiveAccess( | 217 static void TestInvalidateExclusiveAccess( |
179 TestData initial_data, MemoryAccess access1, MemoryAccess access2, | 218 TestData initial_data, MemoryAccess access1, MemoryAccess access2, |
180 MemoryAccess access3, int expected_res, TestData expected_data) { | 219 MemoryAccess access3, int expected_res, TestData expected_data) { |
181 Isolate* isolate = CcTest::i_isolate(); | 220 Isolate* isolate = CcTest::i_isolate(); |
182 HandleScope scope(isolate); | 221 HandleScope scope(isolate); |
183 MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); | 222 MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
184 | 223 |
185 AssembleLoadExcl(&masm, access1, w1, x1); | 224 AssembleLoadExcl(&masm, access1, w1, x1); |
186 AssembleMemoryAccess(&masm, access2, w3, w2, x1); | 225 AssembleMemoryAccess(&masm, access2, w3, w2, x1); |
187 AssembleStoreExcl(&masm, access3, w0, w3, x1); | 226 AssembleStoreExcl(&masm, access3, w0, w3, x1); |
188 __ br(lr); | 227 __ Br(lr); |
189 | 228 |
190 CodeDesc desc; | 229 CodeDesc desc; |
191 masm.GetCode(&desc); | 230 masm.GetCode(&desc); |
192 Handle<Code> code = isolate->factory()->NewCode( | 231 Handle<Code> code = isolate->factory()->NewCode( |
193 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); | 232 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
194 TestData t = initial_data; | 233 TestData t = initial_data; |
195 Simulator::CallArgument args[] = { | 234 Simulator::CallArgument args[] = { |
196 Simulator::CallArgument(reinterpret_cast<uintptr_t>(&t)), | 235 Simulator::CallArgument(reinterpret_cast<uintptr_t>(&t)), |
197 Simulator::CallArgument::End()}; | 236 Simulator::CallArgument::End()}; |
198 Simulator::current(isolate)->CallVoid(code->entry(), args); | 237 Simulator::current(isolate)->CallVoid(code->entry(), args); |
199 int res = Simulator::current(isolate)->wreg(0); | 238 int res = Simulator::current(isolate)->wreg(0); |
200 | 239 |
201 CHECK_EQ(expected_res, res); | 240 CHECK_EQ(expected_res, res); |
202 switch (access3.size) { | 241 switch (access3.size) { |
203 case MemoryAccess::Size::Byte: | 242 case MemoryAccess::Size::Byte: |
204 CHECK_EQ(expected_data.b, t.b); | 243 CHECK_EQ(expected_data.b, t.b); |
205 break; | 244 break; |
206 | 245 |
207 case MemoryAccess::Size::HalfWord: | 246 case MemoryAccess::Size::HalfWord: |
208 CHECK_EQ(expected_data.h, t.h); | 247 CHECK_EQ(expected_data.h, t.h); |
209 break; | 248 break; |
210 | 249 |
211 case MemoryAccess::Size::Word: | 250 case MemoryAccess::Size::Word: |
212 CHECK_EQ(expected_data.w, t.w); | 251 CHECK_EQ(expected_data.w, t.w); |
213 break; | 252 break; |
214 } | 253 } |
215 } | 254 } |
216 | 255 |
217 TEST(simulator_invalidate_exclusive_access) { | 256 TEST(simulator_invalidate_acquire_release_exclusive_access) { |
218 using Kind = MemoryAccess::Kind; | 257 using Kind = MemoryAccess::Kind; |
219 using Size = MemoryAccess::Size; | 258 using Size = MemoryAccess::Size; |
220 | 259 |
221 MemoryAccess ldaxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); | 260 MemoryAccess ldaxr_w(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, w)); |
222 MemoryAccess stlxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); | 261 MemoryAccess stlxr_w(Kind::StoreRelExcl, Size::Word, offsetof(TestData, w), |
| 262 7); |
223 | 263 |
224 // Address mismatch. | 264 // Address mismatch. |
225 TestInvalidateExclusiveAccess( | 265 TestInvalidateExclusiveAccess( |
226 TestData(1), ldaxr_w, | 266 TestData(1), ldaxr_w, |
227 MemoryAccess(Kind::LoadExcl, Size::Word, offsetof(TestData, dummy)), | 267 MemoryAccess(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, dummy)), |
228 stlxr_w, 1, TestData(1)); | 268 stlxr_w, 1, TestData(1)); |
229 | 269 |
230 // Size mismatch. | 270 // Size mismatch. |
231 TestInvalidateExclusiveAccess( | 271 TestInvalidateExclusiveAccess(TestData(1), ldaxr_w, MemoryAccess(), |
232 TestData(1), ldaxr_w, MemoryAccess(), | 272 MemoryAccess(Kind::StoreRelExcl, Size::HalfWord, |
233 MemoryAccess(Kind::StoreExcl, Size::HalfWord, offsetof(TestData, w), 7), | 273 offsetof(TestData, w), 7), |
234 1, TestData(1)); | 274 1, TestData(1)); |
235 | 275 |
236 // Load between ldaxr/stlxr. | 276 // Load between ldaxr/stlxr. |
237 TestInvalidateExclusiveAccess( | 277 TestInvalidateExclusiveAccess( |
238 TestData(1), ldaxr_w, | 278 TestData(1), ldaxr_w, |
239 MemoryAccess(Kind::Load, Size::Word, offsetof(TestData, dummy)), stlxr_w, | 279 MemoryAccess(Kind::Load, Size::Word, offsetof(TestData, dummy)), stlxr_w, |
240 1, TestData(1)); | 280 1, TestData(1)); |
241 | 281 |
242 // Store between ldaxr/stlxr. | 282 // Store between ldaxr/stlxr. |
243 TestInvalidateExclusiveAccess( | 283 TestInvalidateExclusiveAccess( |
244 TestData(1), ldaxr_w, | 284 TestData(1), ldaxr_w, |
245 MemoryAccess(Kind::Store, Size::Word, offsetof(TestData, dummy)), stlxr_w, | 285 MemoryAccess(Kind::Store, Size::Word, offsetof(TestData, dummy)), stlxr_w, |
246 1, TestData(1)); | 286 1, TestData(1)); |
247 | 287 |
248 // Match | 288 // Match |
249 TestInvalidateExclusiveAccess(TestData(1), ldaxr_w, MemoryAccess(), stlxr_w, | 289 TestInvalidateExclusiveAccess(TestData(1), ldaxr_w, MemoryAccess(), stlxr_w, |
250 0, TestData(7)); | 290 0, TestData(7)); |
251 } | 291 } |
252 | 292 |
| 293 TEST(simulator_invalidate_exclusive_access) { |
| 294 using Kind = MemoryAccess::Kind; |
| 295 using Size = MemoryAccess::Size; |
| 296 |
| 297 MemoryAccess ldxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
| 298 MemoryAccess stxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 42); |
| 299 |
| 300 // Address mismatch. |
| 301 TestInvalidateExclusiveAccess( |
| 302 TestData(1), ldxr_w, |
| 303 MemoryAccess(Kind::LoadExcl, Size::Word, offsetof(TestData, dummy)), |
| 304 stxr_w, 1, TestData(1)); |
| 305 |
| 306 // Size mismatch. |
| 307 TestInvalidateExclusiveAccess( |
| 308 TestData(1), ldxr_w, MemoryAccess(), |
| 309 MemoryAccess(Kind::StoreExcl, Size::HalfWord, offsetof(TestData, w), 42), |
| 310 1, TestData(1)); |
| 311 |
| 312 // Load between ldxr/stxr. |
| 313 TestInvalidateExclusiveAccess( |
| 314 TestData(1), ldxr_w, |
| 315 MemoryAccess(Kind::Load, Size::Word, offsetof(TestData, dummy)), stxr_w, |
| 316 1, TestData(1)); |
| 317 |
| 318 // Store between ldxr/stxr. |
| 319 TestInvalidateExclusiveAccess( |
| 320 TestData(1), ldxr_w, |
| 321 MemoryAccess(Kind::Store, Size::Word, offsetof(TestData, dummy)), stxr_w, |
| 322 1, TestData(1)); |
| 323 |
| 324 // Match |
| 325 TestInvalidateExclusiveAccess(TestData(1), ldxr_w, MemoryAccess(), stxr_w, 0, |
| 326 TestData(42)); |
| 327 } |
| 328 |
253 static int ExecuteMemoryAccess(Isolate* isolate, TestData* test_data, | 329 static int ExecuteMemoryAccess(Isolate* isolate, TestData* test_data, |
254 MemoryAccess access) { | 330 MemoryAccess access) { |
255 HandleScope scope(isolate); | 331 HandleScope scope(isolate); |
256 MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); | 332 MacroAssembler masm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); |
257 AssembleMemoryAccess(&masm, access, w0, w2, x1); | 333 AssembleMemoryAccess(&masm, access, w0, w2, x1); |
258 __ br(lr); | 334 __ br(lr); |
259 | 335 |
260 CodeDesc desc; | 336 CodeDesc desc; |
261 masm.GetCode(&desc); | 337 masm.GetCode(&desc); |
262 Handle<Code> code = isolate->factory()->NewCode( | 338 Handle<Code> code = isolate->factory()->NewCode( |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 TestData* test_data_; | 400 TestData* test_data_; |
325 MemoryAccess access_; | 401 MemoryAccess access_; |
326 bool is_finished_; | 402 bool is_finished_; |
327 bool has_request_; | 403 bool has_request_; |
328 bool did_request_; | 404 bool did_request_; |
329 v8::base::Mutex mutex_; | 405 v8::base::Mutex mutex_; |
330 v8::base::ConditionVariable has_request_cv_; | 406 v8::base::ConditionVariable has_request_cv_; |
331 v8::base::ConditionVariable did_request_cv_; | 407 v8::base::ConditionVariable did_request_cv_; |
332 }; | 408 }; |
333 | 409 |
334 TEST(simulator_invalidate_exclusive_access_threaded) { | 410 TEST(simulator_invalidate_acquire_release_exclusive_access_threaded) { |
335 using Kind = MemoryAccess::Kind; | 411 using Kind = MemoryAccess::Kind; |
336 using Size = MemoryAccess::Size; | 412 using Size = MemoryAccess::Size; |
337 | 413 |
338 Isolate* isolate = CcTest::i_isolate(); | 414 Isolate* isolate = CcTest::i_isolate(); |
339 HandleScope scope(isolate); | 415 HandleScope scope(isolate); |
340 | 416 |
341 TestData test_data(1); | 417 TestData test_data(1); |
342 | 418 |
343 MemoryAccessThread thread; | 419 MemoryAccessThread thread; |
344 thread.Start(); | 420 thread.Start(); |
345 | 421 |
346 MemoryAccess ldaxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); | 422 MemoryAccess ldaxr_w(Kind::LoadAcqExcl, Size::Word, offsetof(TestData, w)); |
347 MemoryAccess stlxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); | 423 MemoryAccess stlxr_w(Kind::StoreRelExcl, Size::Word, offsetof(TestData, w), |
| 424 7); |
348 | 425 |
349 // Exclusive store completed by another thread first. | 426 // Exclusive store completed by another thread first. |
350 test_data = TestData(1); | 427 test_data = TestData(1); |
351 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, | 428 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadAcqExcl, Size::Word, |
352 offsetof(TestData, w))); | 429 offsetof(TestData, w))); |
353 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); | 430 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
354 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, | 431 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreRelExcl, Size::Word, |
355 offsetof(TestData, w), 5)); | 432 offsetof(TestData, w), 5)); |
356 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); | 433 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
357 CHECK_EQ(5, test_data.w); | 434 CHECK_EQ(5, test_data.w); |
358 | 435 |
359 // Exclusive store completed by another thread; different address, but masked | 436 // Exclusive store completed by another thread; different address, but masked |
360 // to same | 437 // to same |
361 test_data = TestData(1); | 438 test_data = TestData(1); |
362 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); | 439 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
363 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, | 440 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadAcqExcl, Size::Word, |
364 offsetof(TestData, dummy))); | 441 offsetof(TestData, dummy))); |
365 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, | 442 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreRelExcl, Size::Word, |
366 offsetof(TestData, dummy), 5)); | 443 offsetof(TestData, dummy), 5)); |
367 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); | 444 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
368 CHECK_EQ(1, test_data.w); | 445 CHECK_EQ(1, test_data.w); |
369 | 446 |
370 // Test failure when store between ldaxr/stlxr. | 447 // Test failure when store between ldaxr/stlxr. |
371 test_data = TestData(1); | 448 test_data = TestData(1); |
372 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); | 449 ExecuteMemoryAccess(isolate, &test_data, ldaxr_w); |
373 thread.NextAndWait(&test_data, MemoryAccess(Kind::Store, Size::Word, | 450 thread.NextAndWait(&test_data, MemoryAccess(Kind::Store, Size::Word, |
374 offsetof(TestData, dummy))); | 451 offsetof(TestData, dummy))); |
375 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); | 452 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stlxr_w)); |
376 CHECK_EQ(1, test_data.w); | 453 CHECK_EQ(1, test_data.w); |
377 | 454 |
378 thread.Finish(); | 455 thread.Finish(); |
379 thread.Join(); | 456 thread.Join(); |
380 } | 457 } |
381 | 458 |
| 459 TEST(simulator_invalidate_exclusive_access_threaded) { |
| 460 using Kind = MemoryAccess::Kind; |
| 461 using Size = MemoryAccess::Size; |
| 462 |
| 463 Isolate* isolate = CcTest::i_isolate(); |
| 464 HandleScope scope(isolate); |
| 465 |
| 466 TestData test_data(1); |
| 467 |
| 468 MemoryAccessThread thread; |
| 469 thread.Start(); |
| 470 |
| 471 MemoryAccess ldxr_w(Kind::LoadExcl, Size::Word, offsetof(TestData, w)); |
| 472 MemoryAccess stxr_w(Kind::StoreExcl, Size::Word, offsetof(TestData, w), 7); |
| 473 |
| 474 // Exclusive store completed by another thread first. |
| 475 test_data = TestData(1); |
| 476 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
| 477 offsetof(TestData, w))); |
| 478 ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
| 479 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
| 480 offsetof(TestData, w), 5)); |
| 481 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
| 482 CHECK_EQ(5, test_data.w); |
| 483 |
| 484 // Exclusive store completed by another thread; different address, but masked |
| 485 // to same |
| 486 test_data = TestData(1); |
| 487 ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
| 488 thread.NextAndWait(&test_data, MemoryAccess(Kind::LoadExcl, Size::Word, |
| 489 offsetof(TestData, dummy))); |
| 490 thread.NextAndWait(&test_data, MemoryAccess(Kind::StoreExcl, Size::Word, |
| 491 offsetof(TestData, dummy), 5)); |
| 492 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
| 493 CHECK_EQ(1, test_data.w); |
| 494 |
| 495 // Test failure when store between ldxr/stxr. |
| 496 test_data = TestData(1); |
| 497 ExecuteMemoryAccess(isolate, &test_data, ldxr_w); |
| 498 thread.NextAndWait(&test_data, MemoryAccess(Kind::Store, Size::Word, |
| 499 offsetof(TestData, dummy))); |
| 500 CHECK_EQ(1, ExecuteMemoryAccess(isolate, &test_data, stxr_w)); |
| 501 CHECK_EQ(1, test_data.w); |
| 502 |
| 503 thread.Finish(); |
| 504 thread.Join(); |
| 505 } |
| 506 |
382 #undef __ | 507 #undef __ |
383 | 508 |
384 #endif // USE_SIMULATOR | 509 #endif // USE_SIMULATOR |
OLD | NEW |