| Index: src/arm/simulator-arm.h
|
| diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
|
| index 48c2d0f44abb0a32580d36c49930d045ea9cc84b..39d9b7f65c186f16bdacaf49605635fb5c06cb3a 100644
|
| --- a/src/arm/simulator-arm.h
|
| +++ b/src/arm/simulator-arm.h
|
| @@ -14,6 +14,8 @@
|
| #define V8_ARM_SIMULATOR_ARM_H_
|
|
|
| #include "src/allocation.h"
|
| +#include "src/base/lazy-instance.h"
|
| +#include "src/base/platform/mutex.h"
|
|
|
| #if !defined(USE_SIMULATOR)
|
| // Running without a simulator on a native arm platform.
|
| @@ -302,19 +304,27 @@ class Simulator {
|
| void PrintStopInfo(uint32_t code);
|
|
|
| // Read and write memory.
|
| + // The *Ex functions are exclusive access. The writes return the strex status:
|
| + // 0 if the write succeeds, and 1 if the write fails.
|
| inline uint8_t ReadBU(int32_t addr);
|
| inline int8_t ReadB(int32_t addr);
|
| + uint8_t ReadExBU(int32_t addr);
|
| inline void WriteB(int32_t addr, uint8_t value);
|
| inline void WriteB(int32_t addr, int8_t value);
|
| + int WriteExB(int32_t addr, uint8_t value);
|
|
|
| inline uint16_t ReadHU(int32_t addr, Instruction* instr);
|
| inline int16_t ReadH(int32_t addr, Instruction* instr);
|
| + uint16_t ReadExHU(int32_t addr, Instruction* instr);
|
| // Note: Overloaded on the sign of the value.
|
| inline void WriteH(int32_t addr, uint16_t value, Instruction* instr);
|
| inline void WriteH(int32_t addr, int16_t value, Instruction* instr);
|
| + int WriteExH(int32_t addr, uint16_t value, Instruction* instr);
|
|
|
| inline int ReadW(int32_t addr, Instruction* instr);
|
| + int ReadExW(int32_t addr, Instruction* instr);
|
| inline void WriteW(int32_t addr, int value, Instruction* instr);
|
| + int WriteExW(int32_t addr, int value, Instruction* instr);
|
|
|
| int32_t* ReadDW(int32_t addr);
|
| void WriteDW(int32_t addr, int32_t value1, int32_t value2);
|
| @@ -437,6 +447,94 @@ class Simulator {
|
| char* desc;
|
| };
|
| StopCountAndDesc watched_stops_[kNumOfWatchedStops];
|
| +
|
| + // Syncronization primitives. See ARM DDI 0406C.b, A2.9.
|
| + enum class MonitorAccess {
|
| + Open,
|
| + Exclusive,
|
| + };
|
| +
|
| + enum class TransactionSize {
|
| + None = 0,
|
| + Byte = 1,
|
| + HalfWord = 2,
|
| + Word = 4,
|
| + };
|
| +
|
| + // The least-significant bits of the address are ignored. The number of bits
|
| + // is implementation-defined, between 3 and 11. See ARM DDI 0406C.b, A3.4.3.
|
| + static const int32_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(int32_t addr);
|
| + void NotifyLoadExcl(int32_t addr, TransactionSize size);
|
| + void NotifyStore(int32_t addr);
|
| + bool NotifyStoreExcl(int32_t addr, TransactionSize size);
|
| +
|
| + private:
|
| + void Clear();
|
| +
|
| + MonitorAccess access_state_;
|
| + int32_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(int32_t addr);
|
| + void NotifyStore_Locked(int32_t addr, bool is_requesting_processor);
|
| + bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor);
|
| +
|
| + MonitorAccess access_state_;
|
| + int32_t tagged_addr_;
|
| + Processor* next_;
|
| + Processor* prev_;
|
| + // A strex 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(int32_t addr, Processor* processor);
|
| + void NotifyStore_Locked(int32_t addr, Processor* processor);
|
| + bool NotifyStoreExcl_Locked(int32_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_;
|
| };
|
|
|
|
|
|
|