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" | |
21 #include "vm/native_arguments.h" | 20 #include "vm/native_arguments.h" |
22 #include "vm/os_thread.h" | 21 #include "vm/os_thread.h" |
23 #include "vm/stack_frame.h" | 22 #include "vm/stack_frame.h" |
24 | 23 |
25 namespace dart { | 24 namespace dart { |
26 | 25 |
27 DEFINE_FLAG(uint64_t, | 26 DEFINE_FLAG(uint64_t, |
28 trace_sim_after, | 27 trace_sim_after, |
29 ULLONG_MAX, | 28 ULLONG_MAX, |
30 "Trace simulator execution after instruction count reached."); | 29 "Trace simulator execution after instruction count reached."); |
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 } | 651 } |
653 // Copy the newly read line into the result. | 652 // Copy the newly read line into the result. |
654 memmove(result + offset, line_buf, len); | 653 memmove(result + offset, line_buf, len); |
655 offset += len; | 654 offset += len; |
656 } | 655 } |
657 ASSERT(result != NULL); | 656 ASSERT(result != NULL); |
658 result[offset] = '\0'; | 657 result[offset] = '\0'; |
659 return result; | 658 return result; |
660 } | 659 } |
661 | 660 |
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 | |
668 void Simulator::InitOnce() { | 661 void Simulator::InitOnce() { |
669 // Setup exclusive access state lock. | |
670 exclusive_access_lock_ = new Mutex(); | |
671 } | 662 } |
672 | 663 |
673 Simulator::Simulator() { | 664 Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) { |
674 // Setup simulator support first. Some of this information is needed to | 665 // Setup simulator support first. Some of this information is needed to |
675 // setup the architecture state. | 666 // setup the architecture state. |
676 // We allocate the stack here, the size is computed as the sum of | 667 // We allocate the stack here, the size is computed as the sum of |
677 // the size specified by the user and the buffer space needed for | 668 // the size specified by the user and the buffer space needed for |
678 // handling stack overflow exceptions. To be safe in potential | 669 // handling stack overflow exceptions. To be safe in potential |
679 // stack underflows we also add some underflow buffer space. | 670 // stack underflows we also add some underflow buffer space. |
680 stack_ = | 671 stack_ = |
681 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + | 672 new char[(OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer + |
682 kSimulatorStackUnderflowSize)]; | 673 kSimulatorStackUnderflowSize)]; |
683 pc_modified_ = false; | 674 pc_modified_ = false; |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1017 int8_t Simulator::ReadB(uword addr) { | 1008 int8_t Simulator::ReadB(uword addr) { |
1018 int8_t* ptr = reinterpret_cast<int8_t*>(addr); | 1009 int8_t* ptr = reinterpret_cast<int8_t*>(addr); |
1019 return *ptr; | 1010 return *ptr; |
1020 } | 1011 } |
1021 | 1012 |
1022 void Simulator::WriteB(uword addr, uint8_t value) { | 1013 void Simulator::WriteB(uword addr, uint8_t value) { |
1023 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); | 1014 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); |
1024 *ptr = value; | 1015 *ptr = value; |
1025 } | 1016 } |
1026 | 1017 |
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 | |
1071 void Simulator::ClearExclusive() { | 1018 void Simulator::ClearExclusive() { |
1072 MutexLocker ml(exclusive_access_lock_); | 1019 exclusive_access_addr_ = 0; |
1073 // Remove the reservation for this thread. | 1020 exclusive_access_value_ = 0; |
1074 SetExclusiveAccess(0); | |
1075 } | 1021 } |
1076 | 1022 |
1077 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { | 1023 intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
1078 MutexLocker ml(exclusive_access_lock_); | 1024 exclusive_access_addr_ = addr; |
1079 SetExclusiveAccess(addr); | 1025 exclusive_access_value_ = ReadW(addr, instr); |
1080 return ReadW(addr, instr); | 1026 return exclusive_access_value_; |
1081 } | 1027 } |
1082 | 1028 |
1083 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { | 1029 intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
1084 MutexLocker ml(exclusive_access_lock_); | 1030 // In a well-formed code store-exclusive instruction should always follow |
1085 bool write_allowed = HasExclusiveAccessAndOpen(addr); | 1031 // a corresponding load-exclusive instruction with the same address. |
1086 if (write_allowed) { | 1032 ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); |
1087 WriteW(addr, value, instr); | 1033 if (exclusive_access_addr_ != addr) { |
| 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) { |
1088 return 0; // Success. | 1042 return 0; // Success. |
1089 } | 1043 } |
1090 return 1; // Failure. | 1044 return 1; // Failure. |
1091 } | 1045 } |
1092 | 1046 |
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 | |
1121 // Returns the top of the stack area to enable checking for stack pointer | 1047 // Returns the top of the stack area to enable checking for stack pointer |
1122 // validity. | 1048 // validity. |
1123 uword Simulator::StackTop() const { | 1049 uword Simulator::StackTop() const { |
1124 // To be safe in potential stack underflows we leave some buffer above and | 1050 // To be safe in potential stack underflows we leave some buffer above and |
1125 // set the stack top. | 1051 // set the stack top. |
1126 return StackBase() + | 1052 return StackBase() + |
1127 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); | 1053 (OSThread::GetSpecifiedStackSize() + OSThread::kStackSizeBuffer); |
1128 } | 1054 } |
1129 | 1055 |
1130 bool Simulator::IsTracingExecution() const { | 1056 bool Simulator::IsTracingExecution() const { |
(...skipping 2699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3830 set_register(CODE_REG, code); | 3756 set_register(CODE_REG, code); |
3831 set_register(PP, pp); | 3757 set_register(PP, pp); |
3832 buf->Longjmp(); | 3758 buf->Longjmp(); |
3833 } | 3759 } |
3834 | 3760 |
3835 } // namespace dart | 3761 } // namespace dart |
3836 | 3762 |
3837 #endif // defined(USING_SIMULATOR) | 3763 #endif // defined(USING_SIMULATOR) |
3838 | 3764 |
3839 #endif // defined TARGET_ARCH_ARM | 3765 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |