diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index 98a993119..ece5375b9 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -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 context.Device.System.KernelContext.Syscall.SleepThread(50 * 1000000); } @@ -972,11 +977,12 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd } [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) { - ulong initialValue = context.RequestData.ReadUInt64(); EventFdFlags flags = (EventFdFlags)context.RequestData.ReadUInt32(); + context.RequestData.BaseStream.Position += 4; // Padding + ulong initialValue = context.RequestData.ReadUInt64(); EventFileDescriptor newEventFile = new EventFileDescriptor(initialValue, flags); diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs index 239e2434c..f84e9b93b 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs @@ -26,8 +26,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd _value = value; _flags = flags; - WriteEvent = new ManualResetEvent(true); - ReadEvent = new ManualResetEvent(true); + WriteEvent = new ManualResetEvent(false); + ReadEvent = new ManualResetEvent(false); + UpdateEventStates(); } public int Refcount { get; set; } @@ -38,6 +39,25 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd 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 buffer) { if (buffer.Length < sizeof(ulong)) @@ -47,10 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return LinuxError.EINVAL; } - ReadEvent.Reset(); - lock (_lock) { + ResetEventStates(); + ref ulong count = ref MemoryMarshal.Cast(buffer)[0]; if (_value == 0) @@ -66,6 +86,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { readSize = 0; + UpdateEventStates(); return LinuxError.EAGAIN; } } @@ -85,8 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd _value = 0; } - ReadEvent.Set(); - + UpdateEventStates(); return LinuxError.SUCCESS; } } @@ -100,10 +120,10 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd return LinuxError.EINVAL; } - WriteEvent.Reset(); - lock (_lock) { + ResetEventStates(); + if (_value > _value + count) { if (Blocking) @@ -114,6 +134,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { writeSize = 0; + UpdateEventStates(); return LinuxError.EAGAIN; } } @@ -123,8 +144,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd _value += count; Monitor.Pulse(_lock); - WriteEvent.Set(); - + UpdateEventStates(); return LinuxError.SUCCESS; } } diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs index 8bd9652bf..6501d1117 100644 --- a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs +++ b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs @@ -68,20 +68,37 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { for (int i = 0; i < events.Count; i++) { + PollEventTypeMask outputEvents = 0; + PollEvent evnt = events[i]; EventFileDescriptor socket = (EventFileDescriptor)evnt.FileDescriptor; - if ((evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Input) || - evnt.Data.InputEvents.HasFlag(PollEventTypeMask.UrgentInput)) - && socket.ReadEvent.WaitOne(0)) + if (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)) && socket.WriteEvent.WaitOne(0)) { - waiters.Add(socket.WriteEvent); + outputEvents |= PollEventTypeMask.Output; + } + + + if (outputEvents != 0) + { + evnt.Data.OutputEvents = outputEvents; + + updatedCount++; } } }