forked from Mirror/Ryujinx
[HLE/Kernel] Fix SetThreadPriority, allow nano seconds values > int.MaxValue, fix on WaitProcessWideKeyAtomic (althrough looks like it still doesn't work properly
This commit is contained in:
parent
62b2124c03
commit
33ae6e544b
6 changed files with 47 additions and 24 deletions
|
@ -22,7 +22,7 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
WaitingThreads = new List<(KThread, AutoResetEvent)>();
|
WaitingThreads = new List<(KThread, AutoResetEvent)>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WaitForSignal(KThread Thread, long Timeout)
|
public bool WaitForSignal(KThread Thread, ulong Timeout)
|
||||||
{
|
{
|
||||||
bool Result = true;
|
bool Result = true;
|
||||||
|
|
||||||
|
@ -37,23 +37,19 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
WaitingThreads.Add((Thread, WaitEvent));
|
WaitingThreads.Add((Thread, WaitEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
Process.Scheduler.Suspend(Thread.ProcessorId);
|
if (Timeout == ulong.MaxValue)
|
||||||
|
|
||||||
if (Timeout < 0)
|
|
||||||
{
|
{
|
||||||
Result = WaitEvent.WaitOne();
|
Result = WaitEvent.WaitOne();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = WaitEvent.WaitOne((int)(Timeout / 1000000));
|
Result = WaitEvent.WaitOne(NsTimeConverter.GetTimeMs(Timeout));
|
||||||
|
|
||||||
lock (WaitingThreads)
|
lock (WaitingThreads)
|
||||||
{
|
{
|
||||||
WaitingThreads.Remove((Thread, WaitEvent));
|
WaitingThreads.Remove((Thread, WaitEvent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Process.Scheduler.Resume(Thread);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
private long MutexAddress;
|
private long MutexAddress;
|
||||||
|
|
||||||
|
private int OwnerThreadHandle;
|
||||||
|
|
||||||
private List<(KThread Thread, AutoResetEvent WaitEvent)> WaitingThreads;
|
private List<(KThread Thread, AutoResetEvent WaitEvent)> WaitingThreads;
|
||||||
|
|
||||||
public MutualExclusion(Process Process, long MutexAddress)
|
public MutualExclusion(Process Process, long MutexAddress)
|
||||||
|
@ -24,8 +26,6 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
public void WaitForLock(KThread RequestingThread)
|
public void WaitForLock(KThread RequestingThread)
|
||||||
{
|
{
|
||||||
int OwnerThreadHandle = Process.Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask;
|
|
||||||
|
|
||||||
WaitForLock(RequestingThread, OwnerThreadHandle);
|
WaitForLock(RequestingThread, OwnerThreadHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,10 +80,14 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
WaitingThreads.RemoveAt(HighestPrioIndex);
|
WaitingThreads.RemoveAt(HighestPrioIndex);
|
||||||
|
|
||||||
Process.Memory.WriteInt32(MutexAddress, HasListeners | Handle);
|
Process.Memory.WriteInt32(MutexAddress, HasListeners | Handle);
|
||||||
|
|
||||||
|
OwnerThreadHandle = Handle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Process.Memory.WriteInt32(MutexAddress, 0);
|
Process.Memory.WriteInt32(MutexAddress, 0);
|
||||||
|
|
||||||
|
OwnerThreadHandle = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
Ryujinx.Core/OsHle/Kernel/NsTimeConverter.cs
Normal file
19
Ryujinx.Core/OsHle/Kernel/NsTimeConverter.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
{
|
||||||
|
static class NsTimeConverter
|
||||||
|
{
|
||||||
|
public static int GetTimeMs(ulong Ns)
|
||||||
|
{
|
||||||
|
ulong Ms = Ns / 1_000_000;
|
||||||
|
|
||||||
|
if (Ms < int.MaxValue)
|
||||||
|
{
|
||||||
|
return (int)Ms;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return int.MaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -85,7 +85,7 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
{
|
{
|
||||||
long HandlesPtr = (long)ThreadState.X1;
|
long HandlesPtr = (long)ThreadState.X1;
|
||||||
int HandlesCount = (int)ThreadState.X2;
|
int HandlesCount = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
ulong Timeout = ThreadState.X3;
|
||||||
|
|
||||||
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
|
@ -115,9 +115,9 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
ulong Result = 0;
|
ulong Result = 0;
|
||||||
|
|
||||||
if (Timeout != -1)
|
if (Timeout != ulong.MaxValue)
|
||||||
{
|
{
|
||||||
HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000));
|
HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
|
||||||
|
|
||||||
if (HandleIndex == WaitHandle.WaitTimeout)
|
if (HandleIndex == WaitHandle.WaitTimeout)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,11 +64,11 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
private void SvcSleepThread(AThreadState ThreadState)
|
private void SvcSleepThread(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
ulong NanoSecs = ThreadState.X0;
|
ulong Ns = ThreadState.X0;
|
||||||
|
|
||||||
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (NanoSecs == 0)
|
if (Ns == 0)
|
||||||
{
|
{
|
||||||
Process.Scheduler.Yield(CurrThread);
|
Process.Scheduler.Yield(CurrThread);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
{
|
{
|
||||||
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
Process.Scheduler.Suspend(CurrThread.ProcessorId);
|
||||||
|
|
||||||
Thread.Sleep((int)(NanoSecs / 1000000));
|
Thread.Sleep(NsTimeConverter.GetTimeMs(Ns));
|
||||||
|
|
||||||
Process.Scheduler.Resume(CurrThread);
|
Process.Scheduler.Resume(CurrThread);
|
||||||
}
|
}
|
||||||
|
@ -103,14 +103,14 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
private void SvcSetThreadPriority(AThreadState ThreadState)
|
private void SvcSetThreadPriority(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int Prio = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
int Handle = (int)ThreadState.X1;
|
int Priority = (int)ThreadState.X1;
|
||||||
|
|
||||||
KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
|
KThread CurrThread = Process.HandleTable.GetData<KThread>(Handle);
|
||||||
|
|
||||||
if (CurrThread != null)
|
if (CurrThread != null)
|
||||||
{
|
{
|
||||||
CurrThread.Priority = Prio;
|
CurrThread.Priority = Priority;
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
long MutexAddress = (long)ThreadState.X0;
|
long MutexAddress = (long)ThreadState.X0;
|
||||||
long CondVarAddress = (long)ThreadState.X1;
|
long CondVarAddress = (long)ThreadState.X1;
|
||||||
int ThreadHandle = (int)ThreadState.X2;
|
int ThreadHandle = (int)ThreadState.X2;
|
||||||
long Timeout = (long)ThreadState.X3;
|
ulong Timeout = ThreadState.X3;
|
||||||
|
|
||||||
KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
|
KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
|
||||||
|
|
||||||
|
@ -69,6 +69,8 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process.Scheduler.Suspend(Thread.ProcessorId);
|
||||||
|
|
||||||
MutualExclusion Mutex = GetMutex(MutexAddress);
|
MutualExclusion Mutex = GetMutex(MutexAddress);
|
||||||
|
|
||||||
Mutex.Unlock();
|
Mutex.Unlock();
|
||||||
|
@ -82,6 +84,8 @@ namespace Ryujinx.Core.OsHle.Kernel
|
||||||
|
|
||||||
Mutex.WaitForLock(Thread);
|
Mutex.WaitForLock(Thread);
|
||||||
|
|
||||||
|
Process.Scheduler.Resume(Thread);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue