aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Kernel/SupervisorCall
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-01-18 20:26:39 -0200
committerGitHub <noreply@github.com>2019-01-18 20:26:39 -0200
commit22bacc618815170c0d186a82e1ea4558e36b7063 (patch)
tree79b97959481fea1ac301da6d4e9dea9b991ece6f /Ryujinx.HLE/HOS/Kernel/SupervisorCall
parent3731d0ce8412c3c48286c242842bcb4940b4ca6d (diff)
Improve kernel IPC implementation (#550)
* Implement some IPC related kernel SVCs properly * Fix BLZ decompression when the segment also has a uncompressed chunck * Set default cpu core on process start from ProgramLoader, remove debug message * Load process capabilities properly on KIPs * Fix a copy/paste error in UnmapPhysicalMemory64 * Implement smarter switching between old and new IPC system to support the old HLE services implementation without the manual switch * Implement RegisterService on sm and AcceptSession (partial) * Misc fixes and improvements on new IPC methods * Move IPC related SVCs into a separate file, and logging on RegisterService (sm) * Some small fixes related to receive list buffers and error cases * Load NSOs using the correct pool partition * Fix corner case on GetMaskFromMinMax where range is 64, doesn't happen in pratice however * Fix send static buffer copy * Session release, implement closing requests on client disconnect * Implement ConnectToPort SVC * KLightSession init
Diffstat (limited to 'Ryujinx.HLE/HOS/Kernel/SupervisorCall')
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs23
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs532
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs4
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs181
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs6
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs30
6 files changed, 558 insertions, 218 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs
index 08340b06..071b3c20 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcHandler.cs
@@ -1,10 +1,7 @@
using ChocolArm64.Events;
using ChocolArm64.Memory;
using ChocolArm64.State;
-using Ryujinx.HLE.HOS.Ipc;
-using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Kernel.Process;
-using Ryujinx.HLE.HOS.Kernel.Threading;
using System;
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
@@ -16,26 +13,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private Horizon _system;
private MemoryManager _memory;
- private struct HleIpcMessage
- {
- public KThread Thread { get; private set; }
- public KSession Session { get; private set; }
- public IpcMessage Message { get; private set; }
- public long MessagePtr { get; private set; }
-
- public HleIpcMessage(
- KThread thread,
- KSession session,
- IpcMessage message,
- long messagePtr)
- {
- Thread = thread;
- Session = session;
- Message = message;
- MessagePtr = messagePtr;
- }
- }
-
public SvcHandler(Switch device, KProcess process)
{
_device = device;
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs
new file mode 100644
index 00000000..54939418
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcIpc.cs
@@ -0,0 +1,532 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.HLE.HOS.Kernel.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Process;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using System.Threading;
+
+namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
+{
+ partial class SvcHandler
+ {
+ private struct HleIpcMessage
+ {
+ public KThread Thread { get; private set; }
+ public KClientSession Session { get; private set; }
+ public IpcMessage Message { get; private set; }
+ public long MessagePtr { get; private set; }
+
+ public HleIpcMessage(
+ KThread thread,
+ KClientSession session,
+ IpcMessage message,
+ long messagePtr)
+ {
+ Thread = thread;
+ Session = session;
+ Message = message;
+ MessagePtr = messagePtr;
+ }
+ }
+
+ public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle)
+ {
+ return ConnectToNamedPort(namePtr, out handle);
+ }
+
+ private KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
+ {
+ handle = 0;
+
+ if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name))
+ {
+ return KernelResult.UserCopyFailed;
+ }
+
+ if (name.Length > 11)
+ {
+ return KernelResult.MaximumExceeded;
+ }
+
+ KAutoObject autoObj = KAutoObject.FindNamedObject(_system, name);
+
+ if (!(autoObj is KClientPort clientPort))
+ {
+ return KernelResult.NotFound;
+ }
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KernelResult result = currentProcess.HandleTable.ReserveHandle(out handle);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ result = clientPort.Connect(out KClientSession clientSession);
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CancelHandleReservation(handle);
+
+ return result;
+ }
+
+ currentProcess.HandleTable.SetReservedHandleObj(handle, clientSession);
+
+ clientSession.DecrementReferenceCount();
+
+ return result;
+ }
+
+ public KernelResult SendSyncRequest64(int handle)
+ {
+ return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.ThreadState.Tpidr, 0x100, handle);
+ }
+
+ public KernelResult SendSyncRequestWithUserBuffer64(ulong messagePtr, ulong size, int handle)
+ {
+ return SendSyncRequest(messagePtr, size, handle);
+ }
+
+ private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle)
+ {
+ byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size);
+
+ KClientSession clientSession = _process.HandleTable.GetObject<KClientSession>(handle);
+
+ if (clientSession == null || clientSession.Service == null)
+ {
+ return SendSyncRequest_(handle);
+ }
+
+ if (clientSession != null)
+ {
+ _system.CriticalSection.Enter();
+
+ KThread currentThread = _system.Scheduler.GetCurrentThread();
+
+ currentThread.SignaledObj = null;
+ currentThread.ObjSyncResult = KernelResult.Success;
+
+ currentThread.Reschedule(ThreadSchedState.Paused);
+
+ IpcMessage message = new IpcMessage(messageData, (long)messagePtr);
+
+ ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
+ currentThread,
+ clientSession,
+ message,
+ (long)messagePtr));
+
+ _system.ThreadCounter.AddCount();
+
+ _system.CriticalSection.Leave();
+
+ return currentThread.ObjSyncResult;
+ }
+ else
+ {
+ Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!");
+
+ return KernelResult.InvalidHandle;
+ }
+ }
+
+ private void ProcessIpcRequest(object state)
+ {
+ HleIpcMessage ipcMessage = (HleIpcMessage)state;
+
+ ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall(
+ _device,
+ _process,
+ _memory,
+ ipcMessage.Session,
+ ipcMessage.Message,
+ ipcMessage.MessagePtr);
+
+ _system.ThreadCounter.Signal();
+
+ ipcMessage.Thread.Reschedule(ThreadSchedState.Running);
+ }
+
+ private KernelResult SendSyncRequest_(int handle)
+ {
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KClientSession session = currentProcess.HandleTable.GetObject<KClientSession>(handle);
+
+ if (session == null)
+ {
+ return KernelResult.InvalidHandle;
+ }
+
+ return session.SendSyncRequest();
+ }
+
+ public KernelResult CreateSession64(
+ bool isLight,
+ ulong namePtr,
+ out int serverSessionHandle,
+ out int clientSessionHandle)
+ {
+ return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle);
+ }
+
+ private KernelResult CreateSession(
+ bool isLight,
+ ulong namePtr,
+ out int serverSessionHandle,
+ out int clientSessionHandle)
+ {
+ serverSessionHandle = 0;
+ clientSessionHandle = 0;
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KResourceLimit resourceLimit = currentProcess.ResourceLimit;
+
+ KernelResult result = KernelResult.Success;
+
+ if (resourceLimit != null && !resourceLimit.Reserve(LimitableResource.Session, 1))
+ {
+ return KernelResult.ResLimitExceeded;
+ }
+
+ if (isLight)
+ {
+ KLightSession session = new KLightSession(_system);
+
+ result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
+
+ if (result == KernelResult.Success)
+ {
+ result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle);
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CloseHandle(serverSessionHandle);
+
+ serverSessionHandle = 0;
+ }
+ }
+
+ session.ServerSession.DecrementReferenceCount();
+ session.ClientSession.DecrementReferenceCount();
+ }
+ else
+ {
+ KSession session = new KSession(_system);
+
+ result = currentProcess.HandleTable.GenerateHandle(session.ServerSession, out serverSessionHandle);
+
+ if (result == KernelResult.Success)
+ {
+ result = currentProcess.HandleTable.GenerateHandle(session.ClientSession, out clientSessionHandle);
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CloseHandle(serverSessionHandle);
+
+ serverSessionHandle = 0;
+ }
+ }
+
+ session.ServerSession.DecrementReferenceCount();
+ session.ClientSession.DecrementReferenceCount();
+ }
+
+ return result;
+ }
+
+ public KernelResult AcceptSession64(int portHandle, out int sessionHandle)
+ {
+ return AcceptSession(portHandle, out sessionHandle);
+ }
+
+ private KernelResult AcceptSession(int portHandle, out int sessionHandle)
+ {
+ sessionHandle = 0;
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KServerPort serverPort = currentProcess.HandleTable.GetObject<KServerPort>(portHandle);
+
+ if (serverPort == null)
+ {
+ return KernelResult.InvalidHandle;
+ }
+
+ KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ KAutoObject session;
+
+ if (serverPort.IsLight)
+ {
+ session = serverPort.AcceptIncomingLightConnection();
+ }
+ else
+ {
+ session = serverPort.AcceptIncomingConnection();
+ }
+
+ if (session != null)
+ {
+ currentProcess.HandleTable.SetReservedHandleObj(handle, session);
+
+ session.DecrementReferenceCount();
+
+ sessionHandle = handle;
+
+ result = KernelResult.Success;
+ }
+ else
+ {
+ currentProcess.HandleTable.CancelHandleReservation(handle);
+
+ result = KernelResult.NotFound;
+ }
+
+ return result;
+ }
+
+ public KernelResult ReplyAndReceive64(
+ ulong handlesPtr,
+ int handlesCount,
+ int replyTargetHandle,
+ long timeout,
+ out int handleIndex)
+ {
+ handleIndex = 0;
+
+ if ((uint)handlesCount > 0x40)
+ {
+ return KernelResult.MaximumExceeded;
+ }
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ ulong copySize = (ulong)((long)handlesCount * 4);
+
+ if (!currentProcess.MemoryManager.InsideAddrSpace(handlesPtr, copySize))
+ {
+ return KernelResult.UserCopyFailed;
+ }
+
+ if (handlesPtr + copySize < handlesPtr)
+ {
+ return KernelResult.UserCopyFailed;
+ }
+
+ int[] handles = new int[handlesCount];
+
+ if (!KernelTransfer.UserToKernelInt32Array(_system, handlesPtr, handles))
+ {
+ return KernelResult.UserCopyFailed;
+ }
+
+ KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount];
+
+ for (int index = 0; index < handlesCount; index++)
+ {
+ KSynchronizationObject obj = currentProcess.HandleTable.GetObject<KSynchronizationObject>(handles[index]);
+
+ if (obj == null)
+ {
+ return KernelResult.InvalidHandle;
+ }
+
+ syncObjs[index] = obj;
+ }
+
+ KernelResult result;
+
+ if (replyTargetHandle != 0)
+ {
+ KServerSession replyTarget = currentProcess.HandleTable.GetObject<KServerSession>(replyTargetHandle);
+
+ if (replyTarget == null)
+ {
+ return KernelResult.InvalidHandle;
+ }
+
+ result = replyTarget.Reply();
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+ }
+
+ while ((result = _system.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == KernelResult.Success)
+ {
+ KServerSession session = currentProcess.HandleTable.GetObject<KServerSession>(handles[handleIndex]);
+
+ if (session == null)
+ {
+ break;
+ }
+
+ if ((result = session.Receive()) != KernelResult.NotFound)
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ public KernelResult CreatePort64(
+ int maxSessions,
+ bool isLight,
+ ulong namePtr,
+ out int serverPortHandle,
+ out int clientPortHandle)
+ {
+ return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
+ }
+
+ private KernelResult CreatePort(
+ int maxSessions,
+ bool isLight,
+ ulong namePtr,
+ out int serverPortHandle,
+ out int clientPortHandle)
+ {
+ serverPortHandle = clientPortHandle = 0;
+
+ if (maxSessions < 1)
+ {
+ return KernelResult.MaximumExceeded;
+ }
+
+ KPort port = new KPort(_system, maxSessions, isLight, (long)namePtr);
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle);
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CloseHandle(clientPortHandle);
+ }
+
+ return result;
+ }
+
+ public KernelResult ManageNamedPort64(ulong namePtr, int maxSessions, out int handle)
+ {
+ return ManageNamedPort(namePtr, maxSessions, out handle);
+ }
+
+ private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle)
+ {
+ handle = 0;
+
+ if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name))
+ {
+ return KernelResult.UserCopyFailed;
+ }
+
+ if (maxSessions < 0 || name.Length > 11)
+ {
+ return KernelResult.MaximumExceeded;
+ }
+
+ if (maxSessions == 0)
+ {
+ return KClientPort.RemoveName(_system, name);
+ }
+
+ KPort port = new KPort(_system, maxSessions, false, 0);
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ result = port.ClientPort.SetName(name);
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CloseHandle(handle);
+ }
+
+ return result;
+ }
+
+ public KernelResult ConnectToPort64(int clientPortHandle, out int clientSessionHandle)
+ {
+ return ConnectToPort(clientPortHandle, out clientSessionHandle);
+ }
+
+ private KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle)
+ {
+ clientSessionHandle = 0;
+
+ KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
+
+ KClientPort clientPort = currentProcess.HandleTable.GetObject<KClientPort>(clientPortHandle);
+
+ if (clientPort == null)
+ {
+ return KernelResult.InvalidHandle;
+ }
+
+ KernelResult result = currentProcess.HandleTable.ReserveHandle(out int handle);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ KAutoObject session;
+
+ if (clientPort.IsLight)
+ {
+ result = clientPort.ConnectLight(out KLightClientSession clientSession);
+
+ session = clientSession;
+ }
+ else
+ {
+ result = clientPort.Connect(out KClientSession clientSession);
+
+ session = clientSession;
+ }
+
+ if (result != KernelResult.Success)
+ {
+ currentProcess.HandleTable.CancelHandleReservation(handle);
+
+ return result;
+ }
+
+ currentProcess.HandleTable.SetReservedHandleObj(handle, session);
+
+ session.DecrementReferenceCount();
+
+ clientSessionHandle = handle;
+
+ return result;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs
index e6590522..388dcc21 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcMemory.cs
@@ -305,7 +305,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result;
}
- KTransferMemory transferMemory = new KTransferMemory(address, size);
+ KTransferMemory transferMemory = new KTransferMemory(_system, address, size);
return _process.HandleTable.GenerateHandle(transferMemory, out handle);
}
@@ -350,7 +350,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
public KernelResult UnmapPhysicalMemory64(ulong address, ulong size)
{
- return MapPhysicalMemory(address, size);
+ return UnmapPhysicalMemory(address, size);
}
private KernelResult UnmapPhysicalMemory(ulong address, ulong size)
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
index b0563356..be136ff0 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcSystem.cs
@@ -2,14 +2,11 @@ using ChocolArm64.Memory;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.HLE.Exceptions;
-using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Kernel.Memory;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.HOS.Kernel.Threading;
-using Ryujinx.HLE.HOS.Services;
-using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{
@@ -82,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private KernelResult CloseHandle(int handle)
{
- object obj = _process.HandleTable.GetObject<object>(handle);
+ KAutoObject obj = _process.HandleTable.GetObject<KAutoObject>(handle);
_process.HandleTable.CloseHandle(handle);
@@ -144,88 +141,6 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _system.Scheduler.GetCurrentThread().Context.ThreadState.CntpctEl0;
}
- public KernelResult ConnectToNamedPort64(ulong namePtr, out int handle)
- {
- return ConnectToNamedPort(namePtr, out handle);
- }
-
- private KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
- {
- string name = MemoryHelper.ReadAsciiString(_memory, (long)namePtr, 8);
-
- //TODO: Validate that app has perms to access the service, and that the service
- //actually exists, return error codes otherwise.
- KSession session = new KSession(ServiceFactory.MakeService(_system, name), name);
-
- return _process.HandleTable.GenerateHandle(session, out handle);
- }
-
- public KernelResult SendSyncRequest64(int handle)
- {
- return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.ThreadState.Tpidr, 0x100, handle);
- }
-
- public KernelResult SendSyncRequestWithUserBuffer64(ulong messagePtr, ulong size, int handle)
- {
- return SendSyncRequest(messagePtr, size, handle);
- }
-
- private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle)
- {
- byte[] messageData = _memory.ReadBytes((long)messagePtr, (long)size);
-
- KSession session = _process.HandleTable.GetObject<KSession>(handle);
-
- if (session != null)
- {
- _system.CriticalSection.Enter();
-
- KThread currentThread = _system.Scheduler.GetCurrentThread();
-
- currentThread.SignaledObj = null;
- currentThread.ObjSyncResult = KernelResult.Success;
-
- currentThread.Reschedule(ThreadSchedState.Paused);
-
- IpcMessage message = new IpcMessage(messageData, (long)messagePtr);
-
- ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
- currentThread,
- session,
- message,
- (long)messagePtr));
-
- _system.ThreadCounter.AddCount();
-
- _system.CriticalSection.Leave();
-
- return currentThread.ObjSyncResult;
- }
- else
- {
- Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!");
-
- return KernelResult.InvalidHandle;
- }
- }
-
- private void ProcessIpcRequest(object state)
- {
- HleIpcMessage ipcMessage = (HleIpcMessage)state;
-
- ipcMessage.Thread.ObjSyncResult = IpcHandler.IpcCall(
- _device,
- _process,
- _memory,
- ipcMessage.Session,
- ipcMessage.Message,
- ipcMessage.MessagePtr);
-
- _system.ThreadCounter.Signal();
-
- ipcMessage.Thread.Reschedule(ThreadSchedState.Running);
- }
-
public KernelResult GetProcessId64(int handle, out long pid)
{
return GetProcessId(handle, out pid);
@@ -664,99 +579,5 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.Success;
}
-
- public KernelResult CreatePort64(
- int maxSessions,
- bool isLight,
- ulong namePtr,
- out int serverPortHandle,
- out int clientPortHandle)
- {
- return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
- }
-
- private KernelResult CreatePort(
- int maxSessions,
- bool isLight,
- ulong namePtr,
- out int serverPortHandle,
- out int clientPortHandle)
- {
- serverPortHandle = clientPortHandle = 0;
-
- if (maxSessions < 1)
- {
- return KernelResult.MaximumExceeded;
- }
-
- KPort port = new KPort(_system);
-
- port.Initialize(maxSessions, isLight, (long)namePtr);
-
- KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
-
- KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ClientPort, out clientPortHandle);
-
- if (result != KernelResult.Success)
- {
- return result;
- }
-
- result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out serverPortHandle);
-
- if (result != KernelResult.Success)
- {
- currentProcess.HandleTable.CloseHandle(clientPortHandle);
- }
-
- return result;
- }
-
- public KernelResult ManageNamedPort64(ulong namePtr, int maxSessions, out int handle)
- {
- return ManageNamedPort(namePtr, maxSessions, out handle);
- }
-
- private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle)
- {
- handle = 0;
-
- if (!KernelTransfer.UserToKernelString(_system, namePtr, 12, out string name))
- {
- return KernelResult.UserCopyFailed;
- }
-
- if (maxSessions < 0 || name.Length > 11)
- {
- return KernelResult.MaximumExceeded;
- }
-
- if (maxSessions == 0)
- {
- return KClientPort.RemoveName(_system, name);
- }
-
- KPort port = new KPort(_system);
-
- KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
-
- KernelResult result = currentProcess.HandleTable.GenerateHandle(port.ServerPort, out handle);
-
- if (result != KernelResult.Success)
- {
- return result;
- }
-
- port.Initialize(maxSessions, false, 0);
-
- result = port.SetName(name);
-
- if (result != KernelResult.Success)
- {
- currentProcess.HandleTable.CloseHandle(handle);
- }
-
- return result;
- }
}
}
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs
index a6111777..cbcb712f 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcTable.cs
@@ -63,11 +63,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
{ 0x33, nameof(SvcHandler.GetThreadContext364) },
{ 0x34, nameof(SvcHandler.WaitForAddress64) },
{ 0x35, nameof(SvcHandler.SignalToAddress64) },
+ { 0x40, nameof(SvcHandler.CreateSession64) },
+ { 0x41, nameof(SvcHandler.AcceptSession64) },
+ { 0x43, nameof(SvcHandler.ReplyAndReceive64) },
{ 0x45, nameof(SvcHandler.CreateEvent64) },
{ 0x65, nameof(SvcHandler.GetProcessList64) },
{ 0x6f, nameof(SvcHandler.GetSystemInfo64) },
{ 0x70, nameof(SvcHandler.CreatePort64) },
- { 0x71, nameof(SvcHandler.ManageNamedPort64) }
+ { 0x71, nameof(SvcHandler.ManageNamedPort64) },
+ { 0x72, nameof(SvcHandler.ConnectToPort64) }
};
_svcTable64 = new Action<SvcHandler, CpuThreadState>[0x80];
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs
index 1e1927fe..64268ff2 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SvcThread.cs
@@ -62,22 +62,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
priority,
cpuCore);
- if (result != KernelResult.Success)
+ if (result == KernelResult.Success)
{
- currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
-
- return result;
+ result = _process.HandleTable.GenerateHandle(thread, out handle);
}
-
- result = _process.HandleTable.GenerateHandle(thread, out handle);
-
- if (result != KernelResult.Success)
+ else
{
- thread.Terminate();
-
currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
}
+ thread.DecrementReferenceCount();
+
return result;
}
@@ -88,11 +83,22 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
private KernelResult StartThread(int handle)
{
- KThread thread = _process.HandleTable.GetObject<KThread>(handle);
+ KThread thread = _process.HandleTable.GetKThread(handle);
if (thread != null)
{
- return thread.Start();
+ thread.IncrementReferenceCount();
+
+ KernelResult result = thread.Start();
+
+ if (result == KernelResult.Success)
+ {
+ thread.IncrementReferenceCount();
+ }
+
+ thread.DecrementReferenceCount();
+
+ return result;
}
else
{