| Index: src/arm64/simulator-arm64.h
|
| diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h
|
| index c8c715a0677dbad216adb318478128e22d0fd881..3016e616e4df8b8d1c41bba8df303f8a0c851125 100644
|
| --- a/src/arm64/simulator-arm64.h
|
| +++ b/src/arm64/simulator-arm64.h
|
| @@ -865,6 +865,97 @@ class Simulator : public DecoderVisitor {
|
| char* last_debugger_input() { return last_debugger_input_; }
|
| char* last_debugger_input_;
|
|
|
| + // Synchronization primitives. See ARM DDI 0487A.a, B2.10. Pair types not
|
| + // implemented.
|
| + enum class MonitorAccess {
|
| + Open,
|
| + Exclusive,
|
| + };
|
| +
|
| + enum class TransactionSize {
|
| + None = 0,
|
| + Byte = 1,
|
| + HalfWord = 2,
|
| + Word = 4,
|
| + };
|
| +
|
| + TransactionSize get_transaction_size(unsigned size);
|
| +
|
| + // The least-significant bits of the address are ignored. The number of bits
|
| + // is implementation-defined, between 3 and 11. See ARM DDI 0487A.a, B2.10.3.
|
| + static const uintptr_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1);
|
| +
|
| + class LocalMonitor {
|
| + public:
|
| + LocalMonitor();
|
| +
|
| + // These functions manage the state machine for the local monitor, but do
|
| + // not actually perform loads and stores. NotifyStoreExcl only returns
|
| + // true if the exclusive store is allowed; the global monitor will still
|
| + // have to be checked to see whether the memory should be updated.
|
| + void NotifyLoad(uintptr_t addr);
|
| + void NotifyLoadExcl(uintptr_t addr, TransactionSize size);
|
| + void NotifyStore(uintptr_t addr);
|
| + bool NotifyStoreExcl(uintptr_t addr, TransactionSize size);
|
| +
|
| + private:
|
| + void Clear();
|
| +
|
| + MonitorAccess access_state_;
|
| + uintptr_t tagged_addr_;
|
| + TransactionSize size_;
|
| + };
|
| +
|
| + class GlobalMonitor {
|
| + public:
|
| + GlobalMonitor();
|
| +
|
| + class Processor {
|
| + public:
|
| + Processor();
|
| +
|
| + private:
|
| + friend class GlobalMonitor;
|
| + // These functions manage the state machine for the global monitor, but do
|
| + // not actually perform loads and stores.
|
| + void Clear_Locked();
|
| + void NotifyLoadExcl_Locked(uintptr_t addr);
|
| + void NotifyStore_Locked(uintptr_t addr, bool is_requesting_processor);
|
| + bool NotifyStoreExcl_Locked(uintptr_t addr, bool is_requesting_processor);
|
| +
|
| + MonitorAccess access_state_;
|
| + uintptr_t tagged_addr_;
|
| + Processor* next_;
|
| + Processor* prev_;
|
| + // A stxr can fail due to background cache evictions. Rather than
|
| + // simulating this, we'll just occasionally introduce cases where an
|
| + // exclusive store fails. This will happen once after every
|
| + // kMaxFailureCounter exclusive stores.
|
| + static const int kMaxFailureCounter = 5;
|
| + int failure_counter_;
|
| + };
|
| +
|
| + // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
|
| + base::Mutex mutex;
|
| +
|
| + void NotifyLoadExcl_Locked(uintptr_t addr, Processor* processor);
|
| + void NotifyStore_Locked(uintptr_t addr, Processor* processor);
|
| + bool NotifyStoreExcl_Locked(uintptr_t addr, Processor* processor);
|
| +
|
| + // Called when the simulator is destroyed.
|
| + void RemoveProcessor(Processor* processor);
|
| +
|
| + private:
|
| + bool IsProcessorInLinkedList_Locked(Processor* processor) const;
|
| + void PrependProcessor_Locked(Processor* processor);
|
| +
|
| + Processor* head_;
|
| + };
|
| +
|
| + LocalMonitor local_monitor_;
|
| + GlobalMonitor::Processor global_monitor_processor_;
|
| + static base::LazyInstance<GlobalMonitor>::type global_monitor_;
|
| +
|
| private:
|
| void Init(FILE* stream);
|
|
|
|
|