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()
|
||||
{
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using ChocolArm64.State;
|
||||
using Ryujinx.HLE.Logging;
|
||||
using Ryujinx.HLE.OsHle.Handles;
|
||||
using System;
|
||||
|
||||
using static Ryujinx.HLE.OsHle.ErrorCode;
|
||||
|
||||
|
@ -139,9 +140,9 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
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);
|
||||
|
||||
|
@ -176,7 +177,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
{
|
||||
lock (Process.ThreadSyncLock)
|
||||
{
|
||||
int MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
||||
int MutexValue = Memory.ReadInt32(MutexAddress);
|
||||
|
||||
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.
|
||||
(KThread OwnerThread, int Count) = PopMutexThreadUnsafe(CurrThread, MutexAddress);
|
||||
|
||||
if (OwnerThread == CurrThread)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
if (OwnerThread != null)
|
||||
{
|
||||
//Remove all waiting mutex from the old owner,
|
||||
|
@ -214,13 +220,12 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
|
||||
int HasListeners = Count >= 2 ? MutexHasListenersMask : 0;
|
||||
|
||||
Process.Memory.WriteInt32(MutexAddress, HasListeners | OwnerThread.WaitHandle);
|
||||
Memory.WriteInt32ToSharedAddr(MutexAddress, HasListeners | OwnerThread.WaitHandle);
|
||||
|
||||
OwnerThread.WaitHandle = 0;
|
||||
OwnerThread.MutexAddress = 0;
|
||||
OwnerThread.CondVarAddress = 0;
|
||||
|
||||
OwnerThread.MutexOwner = null;
|
||||
OwnerThread.MutexOwner = null;
|
||||
|
||||
OwnerThread.UpdatePriority();
|
||||
|
||||
|
@ -230,7 +235,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
}
|
||||
else
|
||||
{
|
||||
Process.Memory.WriteInt32(MutexAddress, 0);
|
||||
Memory.WriteInt32ToSharedAddr(MutexAddress, 0);
|
||||
|
||||
Ns.Log.PrintDebug(LogClass.KernelSvc, "No threads waiting mutex!");
|
||||
}
|
||||
|
@ -316,7 +321,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
|
||||
Memory.SetExclusive(ThreadState, MutexAddress);
|
||||
|
||||
int MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
||||
int MutexValue = Memory.ReadInt32(MutexAddress);
|
||||
|
||||
while (MutexValue != 0)
|
||||
{
|
||||
|
@ -325,7 +330,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
//Wait until the lock is released.
|
||||
InsertWaitingMutexThreadUnsafe(MutexValue & ~MutexHasListenersMask, WaitThread);
|
||||
|
||||
Process.Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask);
|
||||
Memory.WriteInt32(MutexAddress, MutexValue | MutexHasListenersMask);
|
||||
|
||||
Memory.ClearExclusiveForStore(ThreadState);
|
||||
|
||||
|
@ -334,7 +339,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
|
||||
Memory.SetExclusive(ThreadState, MutexAddress);
|
||||
|
||||
MutexValue = Process.Memory.ReadInt32(MutexAddress);
|
||||
MutexValue = Memory.ReadInt32(MutexAddress);
|
||||
}
|
||||
|
||||
Ns.Log.PrintDebug(LogClass.KernelSvc, "MutexValue = " + MutexValue.ToString("x8"));
|
||||
|
@ -342,7 +347,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
|||
if (MutexValue == 0)
|
||||
{
|
||||
//Give the lock to this thread.
|
||||
Process.Memory.WriteInt32(MutexAddress, WaitThread.WaitHandle);
|
||||
Memory.WriteInt32ToSharedAddr(MutexAddress, WaitThread.WaitHandle);
|
||||
|
||||
WaitThread.WaitHandle = 0;
|
||||
WaitThread.MutexAddress = 0;
|
||||
|
|
Loading…
Add table
Reference in a new issue