bsd: Fix eventfd broken logic (#3647)
* bsd: Fix eventfd broken logic This commit fix eventfd logic being broken. The following changes were made: - EventFd IPC definition had argument inverted - EventFd events weren't fired correctly - Poll logic was wrong and unfinished for eventfd - Reintroduce workaround from #3385 but in a safer way, and spawn 4 threads. * ipc: Rework a bit for multithreads * Clean up debug logs * Make server thread yield when managed lock isn't availaible * Fix replyTargetHandle not being added in the proper locking scope * Simplify some scopes * Address gdkchan's comments * Revert IPC workaround for now * Reintroduce the EventFileDescriptor workaround
This commit is contained in:
parent
18b61aff59
commit
1865ea87e5
3 changed files with 60 additions and 17 deletions
|
@ -315,6 +315,11 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updateCount > 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// If we are here, that mean nothing was availaible, sleep for 50ms
|
// If we are here, that mean nothing was availaible, sleep for 50ms
|
||||||
context.Device.System.KernelContext.Syscall.SleepThread(50 * 1000000);
|
context.Device.System.KernelContext.Syscall.SleepThread(50 * 1000000);
|
||||||
}
|
}
|
||||||
|
@ -972,11 +977,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
}
|
}
|
||||||
|
|
||||||
[CommandHipc(31)] // 7.0.0+
|
[CommandHipc(31)] // 7.0.0+
|
||||||
// EventFd(u64 initval, nn::socket::EventFdFlags flags) -> (i32 ret, u32 bsd_errno)
|
// EventFd(nn::socket::EventFdFlags flags, u64 initval) -> (i32 ret, u32 bsd_errno)
|
||||||
public ResultCode EventFd(ServiceCtx context)
|
public ResultCode EventFd(ServiceCtx context)
|
||||||
{
|
{
|
||||||
ulong initialValue = context.RequestData.ReadUInt64();
|
|
||||||
EventFdFlags flags = (EventFdFlags)context.RequestData.ReadUInt32();
|
EventFdFlags flags = (EventFdFlags)context.RequestData.ReadUInt32();
|
||||||
|
context.RequestData.BaseStream.Position += 4; // Padding
|
||||||
|
ulong initialValue = context.RequestData.ReadUInt64();
|
||||||
|
|
||||||
EventFileDescriptor newEventFile = new EventFileDescriptor(initialValue, flags);
|
EventFileDescriptor newEventFile = new EventFileDescriptor(initialValue, flags);
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
_value = value;
|
_value = value;
|
||||||
_flags = flags;
|
_flags = flags;
|
||||||
|
|
||||||
WriteEvent = new ManualResetEvent(true);
|
WriteEvent = new ManualResetEvent(false);
|
||||||
ReadEvent = new ManualResetEvent(true);
|
ReadEvent = new ManualResetEvent(false);
|
||||||
|
UpdateEventStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Refcount { get; set; }
|
public int Refcount { get; set; }
|
||||||
|
@ -38,6 +39,25 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
ReadEvent.Dispose();
|
ReadEvent.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ResetEventStates()
|
||||||
|
{
|
||||||
|
WriteEvent.Reset();
|
||||||
|
ReadEvent.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateEventStates()
|
||||||
|
{
|
||||||
|
if (_value > 0)
|
||||||
|
{
|
||||||
|
ReadEvent.Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_value != uint.MaxValue - 1)
|
||||||
|
{
|
||||||
|
WriteEvent.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public LinuxError Read(out int readSize, Span<byte> buffer)
|
public LinuxError Read(out int readSize, Span<byte> buffer)
|
||||||
{
|
{
|
||||||
if (buffer.Length < sizeof(ulong))
|
if (buffer.Length < sizeof(ulong))
|
||||||
|
@ -47,10 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
return LinuxError.EINVAL;
|
return LinuxError.EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadEvent.Reset();
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
ResetEventStates();
|
||||||
|
|
||||||
ref ulong count = ref MemoryMarshal.Cast<byte, ulong>(buffer)[0];
|
ref ulong count = ref MemoryMarshal.Cast<byte, ulong>(buffer)[0];
|
||||||
|
|
||||||
if (_value == 0)
|
if (_value == 0)
|
||||||
|
@ -66,6 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
readSize = 0;
|
readSize = 0;
|
||||||
|
|
||||||
|
UpdateEventStates();
|
||||||
return LinuxError.EAGAIN;
|
return LinuxError.EAGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,8 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
_value = 0;
|
_value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadEvent.Set();
|
UpdateEventStates();
|
||||||
|
|
||||||
return LinuxError.SUCCESS;
|
return LinuxError.SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,10 +120,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
return LinuxError.EINVAL;
|
return LinuxError.EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteEvent.Reset();
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
ResetEventStates();
|
||||||
|
|
||||||
if (_value > _value + count)
|
if (_value > _value + count)
|
||||||
{
|
{
|
||||||
if (Blocking)
|
if (Blocking)
|
||||||
|
@ -114,6 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
writeSize = 0;
|
writeSize = 0;
|
||||||
|
|
||||||
|
UpdateEventStates();
|
||||||
return LinuxError.EAGAIN;
|
return LinuxError.EAGAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,8 +144,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
_value += count;
|
_value += count;
|
||||||
Monitor.Pulse(_lock);
|
Monitor.Pulse(_lock);
|
||||||
|
|
||||||
WriteEvent.Set();
|
UpdateEventStates();
|
||||||
|
|
||||||
return LinuxError.SUCCESS;
|
return LinuxError.SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,20 +68,37 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
|
||||||
{
|
{
|
||||||
for (int i = 0; i < events.Count; i++)
|
for (int i = 0; i < events.Count; i++)
|
||||||
{
|
{
|
||||||
|
PollEventTypeMask outputEvents = 0;
|
||||||
|
|
||||||
PollEvent evnt = events[i];
|
PollEvent evnt = events[i];
|
||||||
|
|
||||||
EventFileDescriptor socket = (EventFileDescriptor)evnt.FileDescriptor;
|
EventFileDescriptor socket = (EventFileDescriptor)evnt.FileDescriptor;
|
||||||
|
|
||||||
if ((evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Input) ||
|
if (socket.ReadEvent.WaitOne(0))
|
||||||
evnt.Data.InputEvents.HasFlag(PollEventTypeMask.UrgentInput))
|
|
||||||
&& socket.ReadEvent.WaitOne(0))
|
|
||||||
{
|
{
|
||||||
waiters.Add(socket.ReadEvent);
|
if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Input))
|
||||||
|
{
|
||||||
|
outputEvents |= PollEventTypeMask.Input;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.UrgentInput))
|
||||||
|
{
|
||||||
|
outputEvents |= PollEventTypeMask.UrgentInput;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output))
|
if ((evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output))
|
||||||
&& socket.WriteEvent.WaitOne(0))
|
&& socket.WriteEvent.WaitOne(0))
|
||||||
{
|
{
|
||||||
waiters.Add(socket.WriteEvent);
|
outputEvents |= PollEventTypeMask.Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (outputEvents != 0)
|
||||||
|
{
|
||||||
|
evnt.Data.OutputEvents = outputEvents;
|
||||||
|
|
||||||
|
updatedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue