| Index: runtime/vm/simulator_mips.cc
 | 
| ===================================================================
 | 
| --- runtime/vm/simulator_mips.cc	(revision 41327)
 | 
| +++ runtime/vm/simulator_mips.cc	(working copy)
 | 
| @@ -16,6 +16,7 @@
 | 
|  #include "vm/assembler.h"
 | 
|  #include "vm/constants_mips.h"
 | 
|  #include "vm/disassembler.h"
 | 
| +#include "vm/lockers.h"
 | 
|  #include "vm/native_arguments.h"
 | 
|  #include "vm/thread.h"
 | 
|  
 | 
| @@ -558,7 +559,16 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// 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();
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -943,6 +953,97 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// Synchronization primitives support.
 | 
| +void Simulator::SetExclusiveAccess(uword addr) {
 | 
| +  Isolate* isolate = Isolate::Current();
 | 
| +  ASSERT(isolate != NULL);
 | 
| +  ASSERT(exclusive_access_lock_->Owner() == isolate);
 | 
| +  int i = 0;
 | 
| +  // Find an entry for this isolate in the exclusive access state.
 | 
| +  while ((i < kNumAddressTags) &&
 | 
| +         (exclusive_access_state_[i].isolate != isolate)) {
 | 
| +    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].isolate = isolate;
 | 
| +  }
 | 
| +  // Remember the address being reserved.
 | 
| +  exclusive_access_state_[i].addr = addr;
 | 
| +}
 | 
| +
 | 
| +
 | 
| +bool Simulator::HasExclusiveAccessAndOpen(uword addr) {
 | 
| +  Isolate* isolate = Isolate::Current();
 | 
| +  ASSERT(isolate != NULL);
 | 
| +  ASSERT(addr != 0);
 | 
| +  ASSERT(exclusive_access_lock_->Owner() == isolate);
 | 
| +  bool result = false;
 | 
| +  for (int i = 0; i < kNumAddressTags; i++) {
 | 
| +    if (exclusive_access_state_[i].isolate == isolate) {
 | 
| +      // Check whether the current isolates 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 isolates 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 isolate.
 | 
| +  SetExclusiveAccess(NULL);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +intptr_t Simulator::ReadExclusiveW(uword addr, Instr* instr) {
 | 
| +  MutexLocker ml(exclusive_access_lock_);
 | 
| +  SetExclusiveAccess(addr);
 | 
| +  return ReadW(addr, instr);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +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.
 | 
| +  }
 | 
| +  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 isolate 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 SC.
 | 
| +    HasExclusiveAccessAndOpen(reinterpret_cast<uword>(address));
 | 
| +  } else {
 | 
| +    // Same effect on exclusive access state as an LL.
 | 
| +    SetExclusiveAccess(reinterpret_cast<uword>(address));
 | 
| +  }
 | 
| +  return value;
 | 
| +}
 | 
| +
 | 
| +
 | 
|  bool Simulator::OverflowFrom(int32_t alu_out,
 | 
|                               int32_t left, int32_t right, bool addition) {
 | 
|    bool overflow;
 | 
| 
 |