OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <setjmp.h> // NOLINT | 5 #include <setjmp.h> // NOLINT |
6 #include <stdlib.h> | 6 #include <stdlib.h> |
7 | 7 |
8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
9 #if defined(TARGET_ARCH_ARM) | 9 #if defined(TARGET_ARCH_ARM) |
10 | 10 |
11 // Only build the simulator if not compiling for real ARM hardware. | 11 // Only build the simulator if not compiling for real ARM hardware. |
12 #if defined(USING_SIMULATOR) | 12 #if defined(USING_SIMULATOR) |
13 | 13 |
14 #include "vm/simulator.h" | 14 #include "vm/simulator.h" |
15 | 15 |
16 #include "vm/assembler.h" | 16 #include "vm/assembler.h" |
17 #include "vm/constants_arm.h" | 17 #include "vm/constants_arm.h" |
18 #include "vm/cpu.h" | 18 #include "vm/cpu.h" |
19 #include "vm/disassembler.h" | 19 #include "vm/disassembler.h" |
| 20 #include "vm/lockers.h" |
20 #include "vm/native_arguments.h" | 21 #include "vm/native_arguments.h" |
21 #include "vm/os_thread.h" | 22 #include "vm/os_thread.h" |
22 #include "vm/stack_frame.h" | 23 #include "vm/stack_frame.h" |
23 | 24 |
24 namespace dart { | 25 namespace dart { |
25 | 26 |
26 DEFINE_FLAG(uint64_t, | 27 DEFINE_FLAG(uint64_t, |
27 trace_sim_after, | 28 trace_sim_after, |
28 ULLONG_MAX, | 29 ULLONG_MAX, |
29 "Trace simulator execution after instruction count reached."); | 30 "Trace simulator execution after instruction count reached."); |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 } | 652 } |
652 // Copy the newly read line into the result. | 653 // Copy the newly read line into the result. |
653 memmove(result + offset, line_buf, len); | 654 memmove(result + offset, line_buf, len); |
654 offset += len; | 655 offset += len; |
655 } | 656 } |
656 ASSERT(result != NULL); | 657 ASSERT(result != NULL); |
657 result[offset] = '\0'; | 658 result[offset] = '\0'; |
658 return result; | 659 return result; |
659 } | 660 } |
660 | 661 |
| 662 // Synchronization primitives support. |
| 663 Mutex* Simulator::exclusive_access_lock_ = NULL; |
| 664 Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
| 665 {NULL, 0}}; |
| 666 int Simulator::next_address_tag_ = 0; |
| 667 |
661 void Simulator::InitOnce() { | 668 void Simulator::InitOnce() { |
| 669 // Setup exclusive access state lock. |
| 670 exclusive_access_lock_ = new Mutex(); |
662 } | 671 } |
663 | 672 |
664 Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) { | 673 Simulator::Simulator() { |
665 // Setup simulator support first. Some of this information is needed to | 674 // Setup simulator support first. Some of this information is needed to |
666 // setup the architecture state. | 675 // setup the architecture state. |
667 // We allocate the stack here, the size is computed as the sum of | 676 // We allocate the stack here, the size is computed as the sum of |
668 // the size specified by the user and the buffer space needed for | 677 // the size specified by the user and the buffer space needed for |
669 // handling stack overflow exceptions. To be safe in potential | 678 // handling stack overflow exceptions. To be safe in potential |
670 // stack underflows we also add some underflow buffer space. | 679 // stack underflows we also add some underflow buffer space. |
671 stack_ = | 680 stack_ = |
672 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + | 681 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
673 kSimulatorStackUnderflowSize)]; | 682 kSimulatorStackUnderflowSize)]; |
674 pc_modified_ = false; | 683 pc_modified_ = false; |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 int8_t Simulator::ReadB(uword addr) { | 1017 int8_t Simulator::ReadB(uword addr) { |
1009 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1018 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
1010 return *ptr; | 1019 return *ptr; |
1011 } | 1020 } |
1012 | 1021 |
1013 void Simulator::WriteB(uword addr, uint8_t value) { | 1022 void Simulator::WriteB(uword addr, uint8_t value) { |
1014 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1023 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1015 *ptr = value; | 1024 *ptr = value; |
1016 } | 1025 } |
1017 | 1026 |
| 1027 // Synchronization primitives support. |
| 1028 void Simulator::SetExclusiveAccess(uword addr) { |
| 1029 Thread* thread = Thread::Current(); |
| 1030 ASSERT(thread != NULL); |
| 1031 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
| 1032 int i = 0; |
| 1033 // Find an entry for this thread in the exclusive access state. |
| 1034 while ((i < kNumAddressTags) && |
| 1035 (exclusive_access_state_[i].thread != thread)) { |
| 1036 i++; |
| 1037 } |
| 1038 // Round-robin replacement of previously used entries. |
| 1039 if (i == kNumAddressTags) { |
| 1040 i = next_address_tag_; |
| 1041 if (++next_address_tag_ == kNumAddressTags) { |
| 1042 next_address_tag_ = 0; |
| 1043 } |
| 1044 exclusive_access_state_[i].thread = thread; |
| 1045 } |
| 1046 // Remember the address being reserved. |
| 1047 exclusive_access_state_[i].addr = addr; |
| 1048 } |
| 1049 |
| 1050 bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
| 1051 Thread* thread = Thread::Current(); |
| 1052 ASSERT(thread != NULL); |
| 1053 ASSERT(addr != 0); |
| 1054 DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
| 1055 bool result = false; |
| 1056 for (int i = 0; i < kNumAddressTags; i++) { |
| 1057 if (exclusive_access_state_[i].thread == thread) { |
| 1058 // Check whether the current thread's address reservation matches. |
| 1059 if (exclusive_access_state_[i].addr == addr) { |
| 1060 result = true; |
| 1061 } |
| 1062 exclusive_access_state_[i].addr = 0; |
| 1063 } else if (exclusive_access_state_[i].addr == addr) { |
| 1064 // Other threads with matching address lose their reservations. |
| 1065 exclusive_access_state_[i].addr = 0; |
| 1066 } |
| 1067 } |
| 1068 return result; |
| 1069 } |
| 1070 |
1018 void Simulator::ClearExclusive() { | 1071 void Simulator::ClearExclusive() { |
1019 exclusive_access_addr_ = 0; | 1072 MutexLocker ml(exclusive_access_lock_); |
1020 exclusive_access_value_ = 0; | 1073 // Remove the reservation for this thread. |
| 1074 SetExclusiveAccess(0); |
1021 } | 1075 } |
1022 | 1076 |
1023 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { | 1077 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
1024 exclusive_access_addr_ = addr; | 1078 MutexLocker ml(exclusive_access_lock_); |
1025 exclusive_access_value_ = ReadW(addr, instr); | 1079 SetExclusiveAccess(addr); |
1026 return exclusive_access_value_; | 1080 return ReadW(addr, instr); |
1027 } | 1081 } |
1028 | 1082 |
1029 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { | 1083 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
1030 // In a well-formed code store-exclusive instruction should always follow | 1084 MutexLocker ml(exclusive_access_lock_); |
1031 // a corresponding load-exclusive instruction with the same address. | 1085 bool write_allowed = HasExclusiveAccessAndOpen(addr); |
1032 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); | 1086 if (write_allowed) { |
1033 if (exclusive_access_addr_ != addr) { | 1087 WriteW(addr, value, instr); |
1034 return 1; // Failure. | |
1035 } | |
1036 | |
1037 uword old_value = exclusive_access_value_; | |
1038 ClearExclusive(); | |
1039 | |
1040 if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr), | |
1041 old_value, value) == old_value) { | |
1042 return 0; // Success. | 1088 return 0; // Success. |
1043 } | 1089 } |
1044 return 1; // Failure. | 1090 return 1; // Failure. |
1045 } | 1091 } |
1046 | 1092 |
| 1093 uword Simulator::CompareExchange(uword* address, |
| 1094 uword compare_value, |
| 1095 uword new_value) { |
| 1096 MutexLocker ml(exclusive_access_lock_); |
| 1097 // We do not get a reservation as it would be guaranteed to be found when |
| 1098 // writing below. No other thread is able to make a reservation while we |
| 1099 // hold the lock. |
| 1100 uword value = *address; |
| 1101 if (value == compare_value) { |
| 1102 *address = new_value; |
| 1103 // Same effect on exclusive access state as a successful STREX. |
| 1104 HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
| 1105 } else { |
| 1106 // Same effect on exclusive access state as an LDREX. |
| 1107 SetExclusiveAccess(reinterpret_cast<uword>(address)); |
| 1108 } |
| 1109 return value; |
| 1110 } |
| 1111 |
| 1112 uint32_t Simulator::CompareExchangeUint32(uint32_t* address, |
| 1113 uint32_t compare_value, |
| 1114 uint32_t new_value) { |
| 1115 COMPILE_ASSERT(sizeof(uword) == sizeof(uint32_t)); |
| 1116 return CompareExchange(reinterpret_cast<uword*>(address), |
| 1117 static_cast<uword>(compare_value), |
| 1118 static_cast<uword>(new_value)); |
| 1119 } |
| 1120 |
1047 // Returns the top of the stack area to enable checking for stack pointer | 1121 // Returns the top of the stack area to enable checking for stack pointer |
1048 // validity. | 1122 // validity. |
1049 uword Simulator::StackTop() const { | 1123 uword Simulator::StackTop() const { |
1050 // To be safe in potential stack underflows we leave some buffer above and | 1124 // To be safe in potential stack underflows we leave some buffer above and |
1051 // set the stack top. | 1125 // set the stack top. |
1052 return StackBase() + | 1126 return StackBase() + |
1053 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1127 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1054 } | 1128 } |
1055 | 1129 |
1056 bool Simulator::IsTracingExecution() const { | 1130 bool Simulator::IsTracingExecution() const { |
(...skipping 2699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3756 set_register(CODE_REG, code); | 3830 set_register(CODE_REG, code); |
3757 set_register(PP, pp); | 3831 set_register(PP, pp); |
3758 buf->Longjmp(); | 3832 buf->Longjmp(); |
3759 } | 3833 } |
3760 | 3834 |
3761 } // namespace dart | 3835 } // namespace dart |
3762 | 3836 |
3763 #endif // defined(USING_SIMULATOR) | 3837 #endif // defined(USING_SIMULATOR) |
3764 | 3838 |
3765 #endif // defined TARGET_ARCH_ARM | 3839 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |