Allow concurrent BSD EventFd read/write (#3385)
This commit is contained in:
parent
830cbf91bb
commit
70895bdb04
5 changed files with 55 additions and 14 deletions
|
@ -309,7 +309,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
// only then doing connections to SM is safe.
|
// only then doing connections to SM is safe.
|
||||||
SmServer.InitDone.WaitOne();
|
SmServer.InitDone.WaitOne();
|
||||||
|
|
||||||
BsdServer = new ServerBase(KernelContext, "BsdServer");
|
BsdServer = new ServerBase(KernelContext, "BsdServer", null, 2);
|
||||||
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
|
AudRenServer = new ServerBase(KernelContext, "AudioRendererServer");
|
||||||
AudOutServer = new ServerBase(KernelContext, "AudioOutServer");
|
AudOutServer = new ServerBase(KernelContext, "AudioOutServer");
|
||||||
FsServer = new ServerBase(KernelContext, "FsServer");
|
FsServer = new ServerBase(KernelContext, "FsServer");
|
||||||
|
|
|
@ -735,11 +735,12 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
ulong argsPtr,
|
ulong argsPtr,
|
||||||
ulong stackTop,
|
ulong stackTop,
|
||||||
int priority,
|
int priority,
|
||||||
int cpuCore)
|
int cpuCore,
|
||||||
|
ThreadStart customThreadStart = null)
|
||||||
{
|
{
|
||||||
lock (_processLock)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2350,6 +2350,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
[PointerSized] ulong stackTop,
|
[PointerSized] ulong stackTop,
|
||||||
int priority,
|
int priority,
|
||||||
int cpuCore)
|
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;
|
handle = 0;
|
||||||
|
|
||||||
|
@ -2386,7 +2398,8 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
|
||||||
argsPtr,
|
argsPtr,
|
||||||
stackTop,
|
stackTop,
|
||||||
priority,
|
priority,
|
||||||
cpuCore);
|
cpuCore,
|
||||||
|
customThreadStart);
|
||||||
|
|
||||||
if (result == KernelResult.Success)
|
if (result == KernelResult.Success)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||||
|
@ -38,15 +39,18 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
private readonly Dictionary<int, Func<IpcService>> _ports = new Dictionary<int, Func<IpcService>>();
|
private readonly Dictionary<int, Func<IpcService>> _ports = new Dictionary<int, Func<IpcService>>();
|
||||||
|
|
||||||
public ManualResetEvent InitDone { get; }
|
public ManualResetEvent InitDone { get; }
|
||||||
public Func<IpcService> SmObjectFactory { get; }
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
public Func<IpcService> SmObjectFactory { get; }
|
||||||
|
|
||||||
public ServerBase(KernelContext context, string name, Func<IpcService> smObjectFactory = null)
|
private int _threadCount;
|
||||||
|
|
||||||
|
public ServerBase(KernelContext context, string name, Func<IpcService> smObjectFactory = null, int threadCount = 1)
|
||||||
{
|
{
|
||||||
InitDone = new ManualResetEvent(false);
|
InitDone = new ManualResetEvent(false);
|
||||||
|
_context = context;
|
||||||
Name = name;
|
Name = name;
|
||||||
SmObjectFactory = smObjectFactory;
|
SmObjectFactory = smObjectFactory;
|
||||||
_context = context;
|
_threadCount = threadCount;
|
||||||
|
|
||||||
const ProcessCreationFlags flags =
|
const ProcessCreationFlags flags =
|
||||||
ProcessCreationFlags.EnableAslr |
|
ProcessCreationFlags.EnableAslr |
|
||||||
|
@ -56,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
|
|
||||||
ProcessCreationInfo creationInfo = new ProcessCreationInfo("Service", 1, 0, 0x8000000, 1, flags, 0, 0);
|
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<IpcService> objectFactory)
|
private void AddPort(int serverPortHandle, Func<IpcService> objectFactory)
|
||||||
|
@ -80,6 +84,32 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
_sessions.Add(serverSessionHandle, obj);
|
_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()
|
private void ServerLoop()
|
||||||
{
|
{
|
||||||
_selfProcess = KernelStatic.GetCurrentProcess();
|
_selfProcess = KernelStatic.GetCurrentProcess();
|
||||||
|
|
|
@ -8,7 +8,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
private ulong _value;
|
private ulong _value;
|
||||||
private readonly EventFdFlags _flags;
|
private readonly EventFdFlags _flags;
|
||||||
private AutoResetEvent _event;
|
|
||||||
|
|
||||||
private object _lock = new object();
|
private object _lock = new object();
|
||||||
|
|
||||||
|
@ -21,7 +20,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
_value = value;
|
_value = value;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
_event = new AutoResetEvent(false);
|
|
||||||
|
|
||||||
WriteEvent = new ManualResetEvent(true);
|
WriteEvent = new ManualResetEvent(true);
|
||||||
ReadEvent = new ManualResetEvent(true);
|
ReadEvent = new ManualResetEvent(true);
|
||||||
|
@ -31,7 +29,6 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_event.Dispose();
|
|
||||||
WriteEvent.Dispose();
|
WriteEvent.Dispose();
|
||||||
ReadEvent.Dispose();
|
ReadEvent.Dispose();
|
||||||
}
|
}
|
||||||
|
@ -57,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
while (_value == 0)
|
while (_value == 0)
|
||||||
{
|
{
|
||||||
_event.WaitOne();
|
Monitor.Wait(_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -106,7 +103,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
if (Blocking)
|
if (Blocking)
|
||||||
{
|
{
|
||||||
_event.WaitOne();
|
Monitor.Wait(_lock);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -119,7 +116,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
writeSize = sizeof(ulong);
|
writeSize = sizeof(ulong);
|
||||||
|
|
||||||
_value += count;
|
_value += count;
|
||||||
_event.Set();
|
Monitor.Pulse(_lock);
|
||||||
|
|
||||||
WriteEvent.Set();
|
WriteEvent.Set();
|
||||||
|
|
||||||
|
|
Reference in a new issue