EventFileDescriptorPollManager.cs 3.4 KB

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