From 70895bdb04c51e92b4d84946c66c122f9d54a73f Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 11 Jun 2022 14:58:30 -0300 Subject: [PATCH] Allow concurrent BSD EventFd read/write (#3385) --- Ryujinx.HLE/HOS/Horizon.cs | 2 +- Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 5 ++- .../HOS/Kernel/SupervisorCall/Syscall.cs | 15 +++++++- Ryujinx.HLE/HOS/Services/ServerBase.cs | 38 +++++++++++++++++-- .../Sockets/Bsd/Impl/EventFileDescriptor.cs | 9 ++--- 5 files changed, 55 insertions(+), 14 deletions(-) diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index b93ebc03..2e64542e 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -309,7 +309,7 @@ namespace Ryujinx.HLE.HOS // only then doing connections to SM is safe. SmServer.InitDone.WaitOne(); - BsdServer = new ServerBase(KernelContext, "BsdServer"); + BsdServer = new ServerBase(KernelContext, "BsdServer", null, 2); AudRenServer = new ServerBase(KernelContext, "AudioRendererServer"); AudOutServer = new ServerBase(KernelContext, "AudioOutServer"); FsServer = new ServerBase(KernelContext, "FsServer"); diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index 0caeacad..d01c3e3b 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -735,11 +735,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process ulong argsPtr, ulong stackTop, int priority, - int cpuCore) + int cpuCore, + ThreadStart customThreadStart = null) { lock (_processLock) { - return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, null); + return thread.Initialize(entrypoint, argsPtr, stackTop, priority, cpuCore, this, ThreadType.User, customThreadStart); } } diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs index 179c7d4b..189e4a3e 100644 --- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs +++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs @@ -2350,6 +2350,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall [PointerSized] ulong stackTop, int priority, int cpuCore) + { + return CreateThread(out handle, entrypoint, argsPtr, stackTop, priority, cpuCore, null); + } + + public KernelResult CreateThread( + out int handle, + ulong entrypoint, + ulong argsPtr, + ulong stackTop, + int priority, + int cpuCore, + ThreadStart customThreadStart) { handle = 0; @@ -2386,7 +2398,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall argsPtr, stackTop, priority, - cpuCore); + cpuCore, + customThreadStart); if (result == KernelResult.Success) { diff --git a/Ryujinx.HLE/HOS/Services/ServerBase.cs b/Ryujinx.HLE/HOS/Services/ServerBase.cs index 90783344..2aead42e 100644 --- a/Ryujinx.HLE/HOS/Services/ServerBase.cs +++ b/Ryujinx.HLE/HOS/Services/ServerBase.cs @@ -1,3 +1,4 @@ +using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Common; @@ -38,15 +39,18 @@ namespace Ryujinx.HLE.HOS.Services private readonly Dictionary> _ports = new Dictionary>(); public ManualResetEvent InitDone { get; } - public Func SmObjectFactory { get; } public string Name { get; } + public Func SmObjectFactory { get; } - public ServerBase(KernelContext context, string name, Func smObjectFactory = null) + private int _threadCount; + + public ServerBase(KernelContext context, string name, Func smObjectFactory = null, int threadCount = 1) { InitDone = new ManualResetEvent(false); + _context = context; Name = name; SmObjectFactory = smObjectFactory; - _context = context; + _threadCount = threadCount; const ProcessCreationFlags flags = ProcessCreationFlags.EnableAslr | @@ -56,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0); - KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, ServerLoop); + KernelStatic.StartInitialProcess(context, creationInfo, DefaultCapabilities, 44, Main); } private void AddPort(int serverPortHandle, Func objectFactory) @@ -80,6 +84,32 @@ namespace Ryujinx.HLE.HOS.Services _sessions.Add(serverSessionHandle, obj); } + private void Main() + { + for (int i = 1; i < _threadCount; i++) + { + KernelResult result = _context.Syscall.CreateThread(out int threadHandle, 0UL, 0UL, 0UL, 44, 3, ServerLoop); + + if (result == KernelResult.Success) + { + result = _context.Syscall.StartThread(threadHandle); + + if (result != KernelResult.Success) + { + Logger.Error?.Print(LogClass.Service, $"Failed to start thread on {Name}: {result}"); + } + + _context.Syscall.CloseHandle(threadHandle); + } + else + { + Logger.Error?.Print(LogClass.Service, $"Failed to create thread on {Name}: {result}"); + } + } + + ServerLoop(); + } + private void ServerLoop() { _selfProcess = KernelStatic.GetCurrentProcess(); diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs index e92b42ef..ea63e842 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs @@ -8,7 +8,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { private ulong _value; private readonly EventFdFlags _flags; - private AutoResetEvent _event; private object _lock = new object(); @@ -21,7 +20,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { _value = value; _flags = flags; - _event = new AutoResetEvent(false); WriteEvent = new ManualResetEvent(true); ReadEvent = new ManualResetEvent(true); @@ -31,7 +29,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd public void Dispose() { - _event.Dispose(); WriteEvent.Dispose(); ReadEvent.Dispose(); } @@ -57,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { while (_value == 0) { - _event.WaitOne(); + Monitor.Wait(_lock); } } else @@ -106,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { if (Blocking) { - _event.WaitOne(); + Monitor.Wait(_lock); } else { @@ -119,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd writeSize = sizeof(ulong); _value += count; - _event.Set(); + Monitor.Pulse(_lock); WriteEvent.Set();