[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:
gdkchan 2018-04-19 04:06:23 -03:00
parent 62b2124c03
commit 33ae6e544b
6 changed files with 47 additions and 24 deletions

View File

@ -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);
} }
} }

View File

@ -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;
} }
} }
} }

View 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;
}
}
}
}

View File

@ -83,9 +83,9 @@ namespace Ryujinx.Core.OsHle.Kernel
private void SvcWaitSynchronization(AThreadState ThreadState) private void SvcWaitSynchronization(AThreadState ThreadState)
{ {
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)
{ {

View File

@ -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;
} }

View File

@ -55,10 +55,10 @@ namespace Ryujinx.Core.OsHle.Kernel
private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState) private void SvcWaitProcessWideKeyAtomic(AThreadState ThreadState)
{ {
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;
} }