diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-03-19 15:58:46 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-03-19 15:58:46 -0300 |
| commit | 4314a8f3e5b76bbf2143f701c06e9354de712027 (patch) | |
| tree | acded3e24125e54bc791f322f0be869f1d379c19 /Ryujinx.Core/OsHle/Svc/SvcSystem.cs | |
| parent | 4940cf0ea58c77c8666d76abdfc35c6380efed4c (diff) | |
[WIP] Add support for events (#60)
* Add support for events, move concept of domains to IpcService
* Support waiting for KThread, remove some test code, other tweaks
* Use move handle on NIFM since I can't test that now, it's better to leave it how it was
Diffstat (limited to 'Ryujinx.Core/OsHle/Svc/SvcSystem.cs')
| -rw-r--r-- | Ryujinx.Core/OsHle/Svc/SvcSystem.cs | 151 |
1 files changed, 103 insertions, 48 deletions
diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs index 9417473c..96bef5e4 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs @@ -3,6 +3,7 @@ using ChocolArm64.State; using Ryujinx.Core.OsHle.Exceptions; using Ryujinx.Core.OsHle.Handles; using Ryujinx.Core.OsHle.Ipc; +using Ryujinx.Core.OsHle.IpcServices; using System; using System.Threading; @@ -34,7 +35,28 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X0; - Process.HandleTable.CloseHandle(Handle); + object Obj = Process.HandleTable.CloseHandle(Handle); + + if (Obj == null) + { + Logging.Warn($"Tried to CloseHandle on invalid handle 0x{Handle:x8}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + + return; + } + + if (Obj is KSession Session) + { + Session.Dispose(); + } + else if (Obj is HTransferMem TMem) + { + TMem.Memory.Manager.Reprotect( + TMem.Position, + TMem.Size, + TMem.Perm); + } ThreadState.X0 = 0; } @@ -43,25 +65,78 @@ namespace Ryujinx.Core.OsHle.Svc { int Handle = (int)ThreadState.X0; - //TODO: Implement events. + KEvent Event = Process.HandleTable.GetData<KEvent>(Handle); - ThreadState.X0 = 0; + if (Event != null) + { + Event.Handle.Reset(); + + ThreadState.X0 = 0; + } + else + { + Logging.Warn($"Tried to ResetSignal on invalid event handle 0x{Handle:x8}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + } } private void SvcWaitSynchronization(AThreadState ThreadState) { - long HandlesPtr = (long)ThreadState.X0; + long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; - //TODO: Implement events. + KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - HThread CurrThread = Process.GetThread(ThreadState.Tpidr); + WaitHandle[] Handles = new WaitHandle[HandlesCount]; + + for (int Index = 0; Index < HandlesCount; Index++) + { + int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); + + KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle); + + if (SyncObj == null) + { + Logging.Warn($"Tried to WaitSynchronization on invalid handle 0x{Handle:x8}!"); + + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + + return; + } + + Handles[Index] = SyncObj.Handle; + } Process.Scheduler.Suspend(CurrThread.ProcessorId); + + int HandleIndex; + + ulong Result = 0; + + if (Timeout != -1) + { + HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000)); + + if (HandleIndex == WaitHandle.WaitTimeout) + { + Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); + } + } + else + { + HandleIndex = WaitHandle.WaitAny(Handles); + } + Process.Scheduler.Resume(CurrThread); - ThreadState.X0 = 0; + ThreadState.X0 = Result; + + if (Result == 0) + { + ThreadState.X1 = (ulong)HandleIndex; + } } private void SvcGetSystemTick(AThreadState ThreadState) @@ -78,8 +153,7 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Validate that app has perms to access the service, and that the service //actually exists, return error codes otherwise. - - HSession Session = new HSession(Process.Services.GetService(Name)); + KSession Session = new KSession(ServiceFactory.MakeService(Name)); ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session); @@ -89,65 +163,46 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcSendSyncRequest(AThreadState ThreadState) { - SendSyncRequest(ThreadState, false); + SendSyncRequest(ThreadState, ThreadState.Tpidr, 0x100, (int)ThreadState.X0); } private void SvcSendSyncRequestWithUserBuffer(AThreadState ThreadState) { - SendSyncRequest(ThreadState, true); + SendSyncRequest( + ThreadState, + (long)ThreadState.X0, + (long)ThreadState.X1, + (int)ThreadState.X2); } - private void SendSyncRequest(AThreadState ThreadState, bool UserBuffer) + private void SendSyncRequest(AThreadState ThreadState, long CmdPtr, long Size, int Handle) { - long CmdPtr = ThreadState.Tpidr; - long Size = 0x100; - int Handle = 0; + KThread CurrThread = Process.GetThread(ThreadState.Tpidr); - if (UserBuffer) - { - CmdPtr = (long)ThreadState.X0; - Size = (long)ThreadState.X1; - Handle = (int)ThreadState.X2; - } - else - { - Handle = (int)ThreadState.X0; - } + byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size); - HThread CurrThread = Process.GetThread(ThreadState.Tpidr); + KSession Session = Process.HandleTable.GetData<KSession>(Handle); - Process.Scheduler.Suspend(CurrThread.ProcessorId); + if (Session != null) + { + Process.Scheduler.Suspend(CurrThread.ProcessorId); - byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size); + IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr); - HSession Session = Process.HandleTable.GetData<HSession>(Handle); + IpcHandler.IpcCall(Ns, Process, Memory, Session, Cmd, CmdPtr); - IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain); + Thread.Yield(); - if (Session != null) - { - IpcHandler.IpcCall( - Ns, - Process, - Memory, - Session, - Cmd, - ThreadState.ThreadId, - CmdPtr, - Handle); - - byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, Size); + Process.Scheduler.Resume(CurrThread); ThreadState.X0 = 0; } else { - ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidIpcReq); - } + Logging.Warn($"Tried to SendSyncRequest on invalid session handle 0x{Handle:x8}!"); - Thread.Yield(); - - Process.Scheduler.Resume(CurrThread); + ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); + } } private void SvcBreak(AThreadState ThreadState) |
