diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-06-21 23:05:42 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-21 23:05:42 -0300 |
| commit | 3e6afeb5134fc699158e8c4d1646a138a947a93d (patch) | |
| tree | 961d66741cf0833c86b6013a653e33e23fc2cbc9 /ChocolArm64 | |
| parent | a4020bb398c72166cecd1457c973e0bebf9d2060 (diff) | |
Fix some thread sync issues (#172)
* Fix some thread sync issues
* Remove some debug stuff
* Ensure that writes to the mutex address clears the exclusive monitor
Diffstat (limited to 'ChocolArm64')
| -rw-r--r-- | ChocolArm64/AThread.cs | 2 | ||||
| -rw-r--r-- | ChocolArm64/Instruction/AInstEmitMemoryEx.cs | 22 | ||||
| -rw-r--r-- | ChocolArm64/Memory/AMemory.cs | 111 |
3 files changed, 68 insertions, 67 deletions
diff --git a/ChocolArm64/AThread.cs b/ChocolArm64/AThread.cs index 040f590e..4fc79d5e 100644 --- a/ChocolArm64/AThread.cs +++ b/ChocolArm64/AThread.cs @@ -46,7 +46,7 @@ namespace ChocolArm64 { Translator.ExecuteSubroutine(this, EntryPoint); - Memory.RemoveMonitor(ThreadId); + Memory.RemoveMonitor(ThreadState); WorkFinished?.Invoke(this, EventArgs.Empty); }); diff --git a/ChocolArm64/Instruction/AInstEmitMemoryEx.cs b/ChocolArm64/Instruction/AInstEmitMemoryEx.cs index a339bb69..ba8eeceb 100644 --- a/ChocolArm64/Instruction/AInstEmitMemoryEx.cs +++ b/ChocolArm64/Instruction/AInstEmitMemoryEx.cs @@ -48,6 +48,16 @@ namespace ChocolArm64.Instruction { AOpCodeMemEx Op = (AOpCodeMemEx)Context.CurrOp; + if (AccType.HasFlag(AccessType.Ordered)) + { + EmitBarrier(Context); + } + + if (AccType.HasFlag(AccessType.Exclusive)) + { + EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn); + } + Context.EmitLdarg(ATranslatedSub.MemoryArgIdx); Context.EmitLdint(Op.Rn); @@ -67,16 +77,6 @@ namespace ChocolArm64.Instruction Context.EmitStintzr(Op.Rt2); } - - if (AccType.HasFlag(AccessType.Exclusive)) - { - EmitMemoryCall(Context, nameof(AMemory.SetExclusive), Op.Rn); - } - - if (AccType.HasFlag(AccessType.Ordered)) - { - EmitBarrier(Context); - } } public static void Pfrm(AILEmitterCtx Context) @@ -150,7 +150,7 @@ namespace ChocolArm64.Instruction Context.EmitLdc_I8(0); Context.EmitStintzr(Op.Rs); - Clrex(Context); + EmitMemoryCall(Context, nameof(AMemory.ClearExclusiveForStore)); } Context.MarkLabel(LblEnd); diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index fe250d4b..c02bf172 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -6,6 +6,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; +using System.Threading; namespace ChocolArm64.Memory { @@ -15,32 +16,18 @@ namespace ChocolArm64.Memory public AMemoryMgr Manager { get; private set; } - private struct ExMonitor + private class ArmMonitor { - public long Position { get; private set; } - - private bool ExState; - - public ExMonitor(long Position, bool ExState) - { - this.Position = Position; - this.ExState = ExState; - } + public long Position; + public bool ExState; public bool HasExclusiveAccess(long Position) { return this.Position == Position && ExState; } - - public void Reset() - { - ExState = false; - } } - private Dictionary<int, ExMonitor> Monitors; - - private HashSet<long> ExAddrs; + private Dictionary<int, ArmMonitor> Monitors; public IntPtr Ram { get; private set; } @@ -50,9 +37,7 @@ namespace ChocolArm64.Memory { Manager = new AMemoryMgr(); - Monitors = new Dictionary<int, ExMonitor>(); - - ExAddrs = new HashSet<long>(); + Monitors = new Dictionary<int, ArmMonitor>(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -66,16 +51,13 @@ namespace ChocolArm64.Memory RamPtr = (byte*)Ram; } - public void RemoveMonitor(int ThreadId) + public void RemoveMonitor(AThreadState State) { lock (Monitors) { - if (Monitors.TryGetValue(ThreadId, out ExMonitor Monitor)) - { - ExAddrs.Remove(Monitor.Position); - } + ClearExclusive(State); - Monitors.Remove(ThreadId); + Monitors.Remove(State.ThreadId); } } @@ -85,66 +67,85 @@ namespace ChocolArm64.Memory lock (Monitors) { - if (Monitors.TryGetValue(ThreadState.ThreadId, out ExMonitor Monitor)) + foreach (ArmMonitor Mon in Monitors.Values) { - ExAddrs.Remove(Monitor.Position); + if (Mon.Position == Position && Mon.ExState) + { + Mon.ExState = false; + } } - bool ExState = ExAddrs.Add(Position); - - Monitor = new ExMonitor(Position, ExState); - - if (!Monitors.TryAdd(ThreadState.ThreadId, Monitor)) + if (!Monitors.TryGetValue(ThreadState.ThreadId, out ArmMonitor ThreadMon)) { - Monitors[ThreadState.ThreadId] = Monitor; + ThreadMon = new ArmMonitor(); + + Monitors.Add(ThreadState.ThreadId, ThreadMon); } + + ThreadMon.Position = Position; + ThreadMon.ExState = true; } } public bool TestExclusive(AThreadState ThreadState, long Position) { + //Note: Any call to this method also should be followed by a + //call to ClearExclusiveForStore if this method returns true. Position &= ~ErgMask; - lock (Monitors) + Monitor.Enter(Monitors); + + if (!Monitors.TryGetValue(ThreadState.ThreadId, out ArmMonitor ThreadMon)) { - if (!Monitors.TryGetValue(ThreadState.ThreadId, out ExMonitor Monitor)) - { - return false; - } + return false; + } + + bool ExState = ThreadMon.HasExclusiveAccess(Position); - return Monitor.HasExclusiveAccess(Position); + if (!ExState) + { + Monitor.Exit(Monitors); } + + return ExState; } - public void ClearExclusive(AThreadState ThreadState) + public void ClearExclusiveForStore(AThreadState ThreadState) { - lock (Monitors) + if (Monitors.TryGetValue(ThreadState.ThreadId, out ArmMonitor ThreadMon)) { - if (Monitors.TryGetValue(ThreadState.ThreadId, out ExMonitor Monitor)) - { - Monitor.Reset(); - ExAddrs.Remove(Monitor.Position); - } + ThreadMon.ExState = false; } + + Monitor.Exit(Monitors); } - public bool AcquireAddress(long Position) + public void ClearExclusive(AThreadState ThreadState) { - Position &= ~ErgMask; - lock (Monitors) { - return ExAddrs.Add(Position); + if (Monitors.TryGetValue(ThreadState.ThreadId, out ArmMonitor ThreadMon)) + { + ThreadMon.ExState = false; + } } } - public void ReleaseAddress(long Position) + public void WriteInt32ToSharedAddr(long Position, int Value) { - Position &= ~ErgMask; + long MaskedPosition = Position & ~ErgMask; lock (Monitors) { - ExAddrs.Remove(Position); + foreach (ArmMonitor Mon in Monitors.Values) + { + if (Mon.Position == MaskedPosition && Mon.ExState) + { + Mon.ExState = false; + } + } + + WriteInt32(Position, Value); } } |
