aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary-nyan <mary@mary.zone>2022-11-27 21:18:05 +0100
committerGitHub <noreply@github.com>2022-11-27 20:18:05 +0000
commit1865ea87e538047efaf36c7a707c30390d620496 (patch)
tree4acebf5eca8b4dd5af8572f6d3a3abaa96f2becb
parent18b61aff59783e0e9dd01c2d45c44406a47b82a9 (diff)
bsd: Fix eventfd broken logic (#3647)1.1.392
* 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
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs10
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptor.cs40
-rw-r--r--Ryujinx.HLE/HOS/Services/Sockets/Bsd/Impl/EventFileDescriptorPollManager.cs27
3 files changed, 60 insertions, 17 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs
index 98a99311..ece5375b 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 239e2434..f84e9b93 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<byte> 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<byte, ulong>(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 8bd9652b..6501d111 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++;
}
}
}