| Index: runtime/vm/simulator_arm.h | 
| diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h | 
| index b81ad9efb32d6f63a5a86a3498ae840042e77986..5a59f5bcdf998d19a60dd1b1984751ce23dab1ab 100644 | 
| --- a/runtime/vm/simulator_arm.h | 
| +++ b/runtime/vm/simulator_arm.h | 
| @@ -104,6 +104,15 @@ class Simulator { | 
| bool fp_return = false, | 
| bool fp_args = false); | 
|  | 
| +  // Implementation of atomic compare and exchange in the same synchronization | 
| +  // domain as other synchronization primitive instructions (e.g. ldrex, strex). | 
| +  static uword CompareExchange(uword* address, | 
| +                               uword compare_value, | 
| +                               uword new_value); | 
| +  static uint32_t CompareExchangeUint32(uint32_t* address, | 
| +                                        uint32_t compare_value, | 
| +                                        uint32_t new_value); | 
| + | 
| // Runtime and native call support. | 
| enum CallKind { | 
| kRuntimeCall, | 
| @@ -209,13 +218,31 @@ class Simulator { | 
| intptr_t ReadExclusiveW(uword addr, Instr* instr); | 
| intptr_t WriteExclusiveW(uword addr, intptr_t value, Instr* instr); | 
|  | 
| -  // Exclusive access reservation: address and value observed during | 
| -  // load-exclusive. Store-exclusive verifies that address is the same and | 
| -  // performs atomic compare-and-swap with remembered value to observe value | 
| -  // changes. This implementation of ldrex/strex instructions does not detect | 
| -  // ABA situation and our uses of ldrex/strex don't need this detection. | 
| -  uword exclusive_access_addr_; | 
| -  uword exclusive_access_value_; | 
| +  // We keep track of 16 exclusive access address tags across all threads. | 
| +  // Since we cannot simulate a native context switch, which clears | 
| +  // the exclusive access state of the local monitor (using the CLREX | 
| +  // instruction), we associate the thread requesting exclusive access to the | 
| +  // address tag. Multiple threads requesting exclusive access (using the LDREX | 
| +  // instruction) to the same address will result in multiple address tags being | 
| +  // created for the same address, one per thread. | 
| +  // At any given time, each thread is associated to at most one address tag. | 
| +  static Mutex* exclusive_access_lock_; | 
| +  static const int kNumAddressTags = 16; | 
| +  static struct AddressTag { | 
| +    Thread* thread; | 
| +    uword addr; | 
| +  } exclusive_access_state_[kNumAddressTags]; | 
| +  static int next_address_tag_; | 
| + | 
| +  // Set access to given address to 'exclusive state' for current thread. | 
| +  static void SetExclusiveAccess(uword addr); | 
| + | 
| +  // Returns true if the current thread has exclusive access to given address, | 
| +  // returns false otherwise. In either case, set access to given address to | 
| +  // 'open state' for all threads. | 
| +  // If given addr is NULL, set access to 'open state' for current | 
| +  // thread (CLREX). | 
| +  static bool HasExclusiveAccessAndOpen(uword addr); | 
|  | 
| // Executing is handled based on the instruction type. | 
| void DecodeType01(Instr* instr);  // Both type 0 and type 1 rolled into one. | 
|  |