Ensure that writes to the mutex address clears the exclusive monitor
This commit is contained in:
parent
11963f2c6a
commit
9f3eb06c61
2 changed files with 34 additions and 11 deletions
|
@ -131,6 +131,24 @@ namespace ChocolArm64.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void WriteInt32ToSharedAddr(long Position, int Value)
|
||||||
|
{
|
||||||
|
long MaskedPosition = Position & ~ErgMask;
|
||||||
|
|
||||||
|
lock (Monitors)
|
||||||
|
{
|
||||||
|
foreach (ArmMonitor Mon in Monitors.Values)
|
||||||
|
{
|
||||||
|
if (Mon.Position == MaskedPosition && Mon.ExState)
|
||||||
|
{
|
||||||
|
Mon.ExState = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteInt32(Position, Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long GetHostPageSize()
|
public long GetHostPageSize()
|
||||||
{
|
{
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
using Ryujinx.HLE.OsHle.Handles;
|
using Ryujinx.HLE.OsHle.Handles;
|
||||||
|
using System;
|
||||||
|
|
||||||
using static Ryujinx.HLE.OsHle.ErrorCode;
|
using static Ryujinx.HLE.OsHle.ErrorCode;
|
||||||
|
|
||||||
|
@ -139,9 +140,9 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread WaitThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (!CondVarWait(CurrThread, ThreadHandle, MutexAddress, CondVarAddress, Timeout))
|
if (!CondVarWait(WaitThread, ThreadHandle, MutexAddress, CondVarAddress, Timeout))
|
||||||
{
|
{
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
|
||||||
|
|
||||||
|
@ -176,7 +177,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
{
|
{
|
||||||
lock (Process.ThreadSyncLock)
|
lock (Process.ThreadSyncLock)
|
||||||
{
|
{
|
||||||
int MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
int MutexValue = Memory.ReadInt32(MutexAddress);
|
||||||
|
|
||||||
Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
|
Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
|
||||||
|
|
||||||
|
@ -204,6 +205,11 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
//If no threads are waiting for the lock, then it should be null.
|
//If no threads are waiting for the lock, then it should be null.
|
||||||
(KThread OwnerThread, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress);
|
(KThread OwnerThread, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress);
|
||||||
|
|
||||||
|
if (OwnerThread == CurrThread)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
if (OwnerThread != null)
|
if (OwnerThread != null)
|
||||||
{
|
{
|
||||||
//Remove all waiting mutex from the old owner,
|
//Remove all waiting mutex from the old owner,
|
||||||
|
@ -214,13 +220,12 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
|
|
||||||
int HasListeners = Count >= 2 ? MutexHasListenersMask : 0;
|
int HasListeners = Count >= 2 ? MutexHasListenersMask : 0;
|
||||||
|
|
||||||
Process.Memory.WriteInt32(MutexAddress, HasListeners | OwnerThread.WaitHandle);
|
Memory.WriteInt32ToSharedAddr(MutexAddress, HasListeners | OwnerThread.WaitHandle);
|
||||||
|
|
||||||
OwnerThread.WaitHandle = 0;
|
OwnerThread.WaitHandle = 0;
|
||||||
OwnerThread.MutexAddress = 0;
|
OwnerThread.MutexAddress = 0;
|
||||||
OwnerThread.CondVarAddress = 0;
|
OwnerThread.CondVarAddress = 0;
|
||||||
|
OwnerThread.MutexOwner = null;
|
||||||
OwnerThread.MutexOwner = null;
|
|
||||||
|
|
||||||
OwnerThread.UpdatePriority();
|
OwnerThread.UpdatePriority();
|
||||||
|
|
||||||
|
@ -230,7 +235,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Process.Memory.WriteInt32(MutexAddress, 0);
|
Memory.WriteInt32ToSharedAddr(MutexAddress, 0);
|
||||||
|
|
||||||
Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!");
|
Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!");
|
||||||
}
|
}
|
||||||
|
@ -316,7 +321,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
|
|
||||||
Memory.SetExclusive(ThreadState, MutexAddress);
|
Memory.SetExclusive(ThreadState, MutexAddress);
|
||||||
|
|
||||||
int MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
int MutexValue = Memory.ReadInt32(MutexAddress);
|
||||||
|
|
||||||
while (MutexValue != 0)
|
while (MutexValue != 0)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +330,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
//Wait until the lock is released.
|
//Wait until the lock is released.
|
||||||
InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread);
|
InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread);
|
||||||
|
|
||||||
Process.Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask);
|
Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask);
|
||||||
|
|
||||||
Memory.ClearExclusiveForStore(ThreadState);
|
Memory.ClearExclusiveForStore(ThreadState);
|
||||||
|
|
||||||
|
@ -334,7 +339,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
|
|
||||||
Memory.SetExclusive(ThreadState, MutexAddress);
|
Memory.SetExclusive(ThreadState, MutexAddress);
|
||||||
|
|
||||||
MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
MutexValue = Memory.ReadInt32(MutexAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
|
Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
|
||||||
|
@ -342,7 +347,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
if (MutexValue == 0)
|
if (MutexValue == 0)
|
||||||
{
|
{
|
||||||
//Give the lock to this thread.
|
//Give the lock to this thread.
|
||||||
Process.Memory.WriteInt32(MutexAddress, WaitThread.WaitHandle);
|
Memory.WriteInt32ToSharedAddr(MutexAddress, WaitThread.WaitHandle);
|
||||||
|
|
||||||
WaitThread.WaitHandle = 0;
|
WaitThread.WaitHandle = 0;
|
||||||
WaitThread.MutexAddress = 0;
|
WaitThread.MutexAddress = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue