EventFileDescriptorPollManager.cs
1 using Ryujinx.Common.Logging; 2 using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types; 3 using System.Collections.Generic; 4 using System.Threading; 5 6 namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl 7 { 8 class EventFileDescriptorPollManager : IPollManager 9 { 10 private static EventFileDescriptorPollManager _instance; 11 12 public static EventFileDescriptorPollManager Instance 13 { 14 get 15 { 16 _instance ??= new EventFileDescriptorPollManager(); 17 18 return _instance; 19 } 20 } 21 22 public bool IsCompatible(PollEvent evnt) 23 { 24 return evnt.FileDescriptor is EventFileDescriptor; 25 } 26 27 public LinuxError Poll(List<PollEvent> events, int timeoutMilliseconds, out int updatedCount) 28 { 29 updatedCount = 0; 30 31 List<ManualResetEvent> waiters = new(); 32 33 for (int i = 0; i < events.Count; i++) 34 { 35 PollEvent evnt = events[i]; 36 37 EventFileDescriptor socket = (EventFileDescriptor)evnt.FileDescriptor; 38 39 bool isValidEvent = false; 40 41 if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Input) || 42 evnt.Data.InputEvents.HasFlag(PollEventTypeMask.UrgentInput)) 43 { 44 waiters.Add(socket.ReadEvent); 45 46 isValidEvent = true; 47 } 48 if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output)) 49 { 50 waiters.Add(socket.WriteEvent); 51 52 isValidEvent = true; 53 } 54 55 if (!isValidEvent) 56 { 57 Logger.Warning?.Print(LogClass.ServiceBsd, $"Unsupported Poll input event type: {evnt.Data.InputEvents}"); 58 59 return LinuxError.EINVAL; 60 } 61 } 62 63 int index = WaitHandle.WaitAny(waiters.ToArray(), timeoutMilliseconds); 64 65 if (index != WaitHandle.WaitTimeout) 66 { 67 for (int i = 0; i < events.Count; i++) 68 { 69 PollEventTypeMask outputEvents = 0; 70 71 PollEvent evnt = events[i]; 72 73 EventFileDescriptor socket = (EventFileDescriptor)evnt.FileDescriptor; 74 75 if (socket.ReadEvent.WaitOne(0)) 76 { 77 if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Input)) 78 { 79 outputEvents |= PollEventTypeMask.Input; 80 } 81 82 if (evnt.Data.InputEvents.HasFlag(PollEventTypeMask.UrgentInput)) 83 { 84 outputEvents |= PollEventTypeMask.UrgentInput; 85 } 86 } 87 88 if ((evnt.Data.InputEvents.HasFlag(PollEventTypeMask.Output)) 89 && socket.WriteEvent.WaitOne(0)) 90 { 91 outputEvents |= PollEventTypeMask.Output; 92 } 93 94 95 if (outputEvents != 0) 96 { 97 evnt.Data.OutputEvents = outputEvents; 98 99 updatedCount++; 100 } 101 } 102 } 103 else 104 { 105 return LinuxError.ETIMEDOUT; 106 } 107 108 return LinuxError.SUCCESS; 109 } 110 111 public LinuxError Select(List<PollEvent> events, int timeout, out int updatedCount) 112 { 113 // TODO: Implement Select for event file descriptors 114 updatedCount = 0; 115 116 return LinuxError.EOPNOTSUPP; 117 } 118 } 119 }