aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Memory
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-06-21 23:05:42 -0300
committerGitHub <noreply@github.com>2018-06-21 23:05:42 -0300
commit3e6afeb5134fc699158e8c4d1646a138a947a93d (patch)
tree961d66741cf0833c86b6013a653e33e23fc2cbc9 /ChocolArm64/Memory
parenta4020bb398c72166cecd1457c973e0bebf9d2060 (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/Memory')
-rw-r--r--ChocolArm64/Memory/AMemory.cs111
1 files changed, 56 insertions, 55 deletions
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);
}
}