Index: runtime/vm/simulator_arm.cc |
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc |
index 60c0731954b9825ea97ddf865be5c28e4b233b6a..6bf16e029f85e237e7ffd02085707130f42ab344 100644 |
--- a/runtime/vm/simulator_arm.cc |
+++ b/runtime/vm/simulator_arm.cc |
@@ -17,7 +17,6 @@ |
#include "vm/constants_arm.h" |
#include "vm/cpu.h" |
#include "vm/disassembler.h" |
-#include "vm/lockers.h" |
#include "vm/native_arguments.h" |
#include "vm/os_thread.h" |
#include "vm/stack_frame.h" |
@@ -659,18 +658,10 @@ char* SimulatorDebugger::ReadLine(const char* prompt) { |
return result; |
} |
-// Synchronization primitives support. |
-Mutex* Simulator::exclusive_access_lock_ = NULL; |
-Simulator::AddressTag Simulator::exclusive_access_state_[kNumAddressTags] = { |
- {NULL, 0}}; |
-int Simulator::next_address_tag_ = 0; |
- |
void Simulator::InitOnce() { |
- // Setup exclusive access state lock. |
- exclusive_access_lock_ = new Mutex(); |
} |
-Simulator::Simulator() { |
+Simulator::Simulator() : exclusive_access_addr_(0), exclusive_access_value_(0) { |
// Setup simulator support first. Some of this information is needed to |
// setup the architecture state. |
// We allocate the stack here, the size is computed as the sum of |
@@ -1024,98 +1015,33 @@ void Simulator::WriteB(uword addr, uint8_t value) { |
*ptr = value; |
} |
-// Synchronization primitives support. |
-void Simulator::SetExclusiveAccess(uword addr) { |
- Thread* thread = Thread::Current(); |
- ASSERT(thread != NULL); |
- DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
- int i = 0; |
- // Find an entry for this thread in the exclusive access state. |
- while ((i < kNumAddressTags) && |
- (exclusive_access_state_[i].thread != thread)) { |
- i++; |
- } |
- // Round-robin replacement of previously used entries. |
- if (i == kNumAddressTags) { |
- i = next_address_tag_; |
- if (++next_address_tag_ == kNumAddressTags) { |
- next_address_tag_ = 0; |
- } |
- exclusive_access_state_[i].thread = thread; |
- } |
- // Remember the address being reserved. |
- exclusive_access_state_[i].addr = addr; |
-} |
- |
-bool Simulator::HasExclusiveAccessAndOpen(uword addr) { |
- Thread* thread = Thread::Current(); |
- ASSERT(thread != NULL); |
- ASSERT(addr != 0); |
- DEBUG_ASSERT(exclusive_access_lock_->IsOwnedByCurrentThread()); |
- bool result = false; |
- for (int i = 0; i < kNumAddressTags; i++) { |
- if (exclusive_access_state_[i].thread == thread) { |
- // Check whether the current thread's address reservation matches. |
- if (exclusive_access_state_[i].addr == addr) { |
- result = true; |
- } |
- exclusive_access_state_[i].addr = 0; |
- } else if (exclusive_access_state_[i].addr == addr) { |
- // Other threads with matching address lose their reservations. |
- exclusive_access_state_[i].addr = 0; |
- } |
- } |
- return result; |
-} |
- |
void Simulator::ClearExclusive() { |
- MutexLocker ml(exclusive_access_lock_); |
- // Remove the reservation for this thread. |
- SetExclusiveAccess(0); |
+ exclusive_access_addr_ = 0; |
+ exclusive_access_value_ = 0; |
} |
intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) { |
- MutexLocker ml(exclusive_access_lock_); |
- SetExclusiveAccess(addr); |
- return ReadW(addr, instr); |
+ exclusive_access_addr_ = addr; |
+ exclusive_access_value_ = ReadW(addr, instr); |
+ return exclusive_access_value_; |
} |
intptr_t Simulator::WriteExclusiveW(uword addr, intptr_t value, Instr* instr) { |
- MutexLocker ml(exclusive_access_lock_); |
- bool write_allowed = HasExclusiveAccessAndOpen(addr); |
- if (write_allowed) { |
- WriteW(addr, value, instr); |
- return 0; // Success. |
+ // In a well-formed code store-exclusive instruction should always follow |
+ // a corresponding load-exclusive instruction with the same address. |
+ ASSERT((exclusive_access_addr_ == 0) || (exclusive_access_addr_ == addr)); |
+ if (exclusive_access_addr_ != addr) { |
+ return 1; // Failure. |
} |
- return 1; // Failure. |
-} |
-uword Simulator::CompareExchange(uword* address, |
- uword compare_value, |
- uword new_value) { |
- MutexLocker ml(exclusive_access_lock_); |
- // We do not get a reservation as it would be guaranteed to be found when |
- // writing below. No other thread is able to make a reservation while we |
- // hold the lock. |
- uword value = *address; |
- if (value == compare_value) { |
- *address = new_value; |
- // Same effect on exclusive access state as a successful STREX. |
- HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address)); |
- } else { |
- // Same effect on exclusive access state as an LDREX. |
- SetExclusiveAccess(reinterpret_cast<uword>(address)); |
- } |
- return value; |
-} |
+ uword old_value = exclusive_access_value_; |
+ ClearExclusive(); |
-uint32_t Simulator::CompareExchangeUint32(uint32_t* address, |
- uint32_t compare_value, |
- uint32_t new_value) { |
- COMPILE_ASSERT(sizeof(uword) == sizeof(uint32_t)); |
- return CompareExchange(reinterpret_cast<uword*>(address), |
- static_cast<uword>(compare_value), |
- static_cast<uword>(new_value)); |
+ if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr), |
+ old_value, value) == old_value) { |
+ return 0; // Success. |
+ } |
+ return 1; // Failure. |
} |
// Returns the top of the stack area to enable checking for stack pointer |