aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTSRBerry <20988865+TSRBerry@users.noreply.github.com>2023-03-19 11:30:04 +0100
committerGitHub <noreply@github.com>2023-03-19 11:30:04 +0100
commitc05c688ee840dc0f8981858d7e723667efdcb8b5 (patch)
treefa4fa5c94290271a594c2a9a027020c49b5f6b8c
parentb2623dc27d14e9c672429a3819d20958954cb170 (diff)
Avoid copying more handles than we have space for (#4564)1.1.670
* Avoid copying more handles than we have space for * Use locks instead * Reduce nesting by combining the lock statements * Add locks for other uses of _sessionHandles and _portHandles * Use one object to lock instead of locking twice * Release the lock as soon as possible
-rw-r--r--Ryujinx.HLE/HOS/Services/ServerBase.cs37
1 files changed, 28 insertions, 9 deletions
diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs
index 619f5448..8b82b771 100644
--- a/Ryujinx.HLE/HOS/Services/ServerBase.cs
+++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs
@@ -32,6 +32,8 @@ namespace Ryujinx.HLE.HOS.Services
0x01007FFF
};
+ private readonly object _handleLock = new();
+
private readonly KernelContext _context;
private KProcess _selfProcess;
@@ -77,7 +79,10 @@ namespace Ryujinx.HLE.HOS.Services
private void AddPort(int serverPortHandle, Func<IpcService> objectFactory)
{
- _portHandles.Add(serverPortHandle);
+ lock (_handleLock)
+ {
+ _portHandles.Add(serverPortHandle);
+ }
_ports.Add(serverPortHandle, objectFactory);
}
@@ -92,7 +97,10 @@ namespace Ryujinx.HLE.HOS.Services
public void AddSessionObj(int serverSessionHandle, IpcService obj)
{
- _sessionHandles.Add(serverSessionHandle);
+ lock (_handleLock)
+ {
+ _sessionHandles.Add(serverSessionHandle);
+ }
_sessions.Add(serverSessionHandle, obj);
}
@@ -126,12 +134,20 @@ namespace Ryujinx.HLE.HOS.Services
while (true)
{
- int handleCount = _portHandles.Count + _sessionHandles.Count;
+ int handleCount;
+ int portHandleCount;
+ int[] handles;
- int[] handles = ArrayPool<int>.Shared.Rent(handleCount);
-
- _portHandles.CopyTo(handles, 0);
- _sessionHandles.CopyTo(handles, _portHandles.Count);
+ lock (_handleLock)
+ {
+ portHandleCount = _portHandles.Count;
+ handleCount = portHandleCount + _sessionHandles.Count;
+
+ handles = ArrayPool<int>.Shared.Rent(handleCount);
+
+ _portHandles.CopyTo(handles, 0);
+ _sessionHandles.CopyTo(handles, portHandleCount);
+ }
// We still need a timeout here to allow the service to pick up and listen new sessions...
var rc = _context.Syscall.ReplyAndReceive(out int signaledIndex, handles.AsSpan(0, handleCount), replyTargetHandle, 1000000L);
@@ -145,7 +161,7 @@ namespace Ryujinx.HLE.HOS.Services
replyTargetHandle = 0;
- if (rc == Result.Success && signaledIndex >= _portHandles.Count)
+ if (rc == Result.Success && signaledIndex >= portHandleCount)
{
// We got a IPC request, process it, pass to the appropriate service if needed.
int signaledHandle = handles[signaledIndex];
@@ -278,7 +294,10 @@ namespace Ryujinx.HLE.HOS.Services
else if (request.Type == IpcMessageType.HipcCloseSession || request.Type == IpcMessageType.TipcCloseSession)
{
_context.Syscall.CloseHandle(serverSessionHandle);
- _sessionHandles.Remove(serverSessionHandle);
+ lock (_handleLock)
+ {
+ _sessionHandles.Remove(serverSessionHandle);
+ }
IpcService service = _sessions[serverSessionHandle];
(service as IDisposable)?.Dispose();
_sessions.Remove(serverSessionHandle);