aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-05-07 15:53:23 -0300
committerGitHub <noreply@github.com>2018-05-07 15:53:23 -0300
commit34037701c708cb70bbf44dea71ee0912f7b4102b (patch)
treeca4cf2bde85dea48af12033b8d0446f17b611f4f /Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
parent4419e8d6b43432eae94a3a9304f7df22b34738a8 (diff)
NvServices refactoring (#120)
* Initial implementation of NvMap/NvHostCtrl * More work on NvHostCtrl * Refactoring of nvservices, move GPU Vmm, make Vmm per-process, refactor most gpu devices, move Gpu to Core, fix CbBind * Implement GetGpuTime, support CancelSynchronization, fix issue on InsertWaitingMutex, proper double buffering support (again, not working properly for commercial games, only hb) * Try to fix perf regression reading/writing textures, moved syncpts and events to a UserCtx class, delete global state when the process exits, other minor tweaks * Remove now unused code, add comment about probably wrong result codes
Diffstat (limited to 'Ryujinx.Core/OsHle/Kernel/SvcSystem.cs')
-rw-r--r--Ryujinx.Core/OsHle/Kernel/SvcSystem.cs85
1 files changed, 68 insertions, 17 deletions
diff --git a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
index 601b211c..e5b080a8 100644
--- a/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Kernel/SvcSystem.cs
@@ -40,7 +40,7 @@ namespace Ryujinx.Core.OsHle.Kernel
if (Obj == null)
{
- Ns.Log.PrintWarning(LogClass.KernelSvc, $"Tried to CloseHandle on invalid handle 0x{Handle:x8}!");
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
@@ -88,9 +88,21 @@ namespace Ryujinx.Core.OsHle.Kernel
int HandlesCount = (int)ThreadState.X2;
ulong Timeout = ThreadState.X3;
+ Ns.Log.PrintDebug(LogClass.KernelSvc,
+ "HandlesPtr = " + HandlesPtr .ToString("x16") + ", " +
+ "HandlesCount = " + HandlesCount.ToString("x8") + ", " +
+ "Timeout = " + Timeout .ToString("x16"));
+
+ if ((uint)HandlesCount > 0x40)
+ {
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange);
+
+ return;
+ }
+
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
- WaitHandle[] Handles = new WaitHandle[HandlesCount];
+ WaitHandle[] Handles = new WaitHandle[HandlesCount + 1];
for (int Index = 0; Index < HandlesCount; Index++)
{
@@ -110,34 +122,73 @@ namespace Ryujinx.Core.OsHle.Kernel
Handles[Index] = SyncObj.WaitEvent;
}
- Process.Scheduler.Suspend(CurrThread.ProcessorId);
+ using (AutoResetEvent WaitEvent = new AutoResetEvent(false))
+ {
+ if (!SyncWaits.TryAdd(CurrThread, WaitEvent))
+ {
+ throw new InvalidOperationException();
+ }
+
+ Handles[HandlesCount] = WaitEvent;
- int HandleIndex;
+ Process.Scheduler.Suspend(CurrThread.ProcessorId);
- ulong Result = 0;
+ int HandleIndex;
- if (Timeout != ulong.MaxValue)
- {
- HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
+ ulong Result = 0;
+
+ if (Timeout != ulong.MaxValue)
+ {
+ HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout));
+ }
+ else
+ {
+ HandleIndex = WaitHandle.WaitAny(Handles);
+ }
if (HandleIndex == WaitHandle.WaitTimeout)
{
Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);
}
+ else if (HandleIndex == HandlesCount)
+ {
+ Result = MakeError(ErrorModule.Kernel, KernelErr.Canceled);
+ }
+
+ SyncWaits.TryRemove(CurrThread, out _);
+
+ Process.Scheduler.Resume(CurrThread);
+
+ ThreadState.X0 = Result;
+
+ if (Result == 0)
+ {
+ ThreadState.X1 = (ulong)HandleIndex;
+ }
}
- else
+ }
+
+ private void SvcCancelSynchronization(AThreadState ThreadState)
+ {
+ int ThreadHandle = (int)ThreadState.X0;
+
+ KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle);
+
+ if (Thread == null)
{
- HandleIndex = WaitHandle.WaitAny(Handles);
- }
+ Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
- Process.Scheduler.Resume(CurrThread);
+ ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
- ThreadState.X0 = Result;
+ return;
+ }
- if (Result == 0)
+ if (SyncWaits.TryRemove(Thread, out AutoResetEvent WaitEvent))
{
- ThreadState.X1 = (ulong)HandleIndex;
+ WaitEvent.Set();
}
+
+ ThreadState.X0 = 0;
}
private void SvcGetSystemTick(AThreadState ThreadState)
@@ -190,13 +241,13 @@ namespace Ryujinx.Core.OsHle.Kernel
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr);
- IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
+ long Result = IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr);
Thread.Yield();
Process.Scheduler.Resume(CurrThread);
- ThreadState.X0 = 0;
+ ThreadState.X0 = (ulong)Result;
}
else
{