Ryujinx-uplift/Ryujinx/OsHle/Mutex.cs
2018-02-04 20:08:20 -03:00

89 lines
2.3 KiB
C#

using ChocolArm64;
using ChocolArm64.Memory;
using System.Threading;
namespace Ryujinx.OsHle
{
class Mutex
{
private const int MutexHasListenersMask = 0x40000000;
private AMemory Memory;
private long MutexAddress;
private int CurrRequestingThreadHandle;
private int HighestPriority;
private ManualResetEvent ThreadEvent;
private object EnterWaitLock;
public Mutex(AMemory Memory, long MutexAddress)
{
this.Memory = Memory;
this.MutexAddress = MutexAddress;
ThreadEvent = new ManualResetEvent(false);
EnterWaitLock = new object();
}
public void WaitForLock(AThread RequestingThread, int RequestingThreadHandle)
{
lock (EnterWaitLock)
{
int CurrentThreadHandle = Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
if (CurrentThreadHandle == RequestingThreadHandle ||
CurrentThreadHandle == 0)
{
return;
}
if (CurrRequestingThreadHandle == 0 || RequestingThread.Priority < HighestPriority)
{
CurrRequestingThreadHandle = RequestingThreadHandle;
HighestPriority = RequestingThread.Priority;
}
}
ThreadEvent.Reset();
ThreadEvent.WaitOne();
}
public void GiveUpLock(int ThreadHandle)
{
lock (EnterWaitLock)
{
int CurrentThread = Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
if (CurrentThread == ThreadHandle)
{
Unlock();
}
}
}
public void Unlock()
{
lock (EnterWaitLock)
{
if (CurrRequestingThreadHandle != 0)
{
Memory.WriteInt32(MutexAddress, CurrRequestingThreadHandle);
}
else
{
Memory.WriteInt32(MutexAddress, 0);
}
CurrRequestingThreadHandle = 0;
ThreadEvent.Set();
}
}
}
}