CondVar.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using ChocolArm64.Memory;
  2. using System.Collections.Concurrent;
  3. using System.Threading;
  4. namespace Ryujinx.OsHle
  5. {
  6. class CondVar
  7. {
  8. private AMemory Memory;
  9. private long CondVarAddress;
  10. private long Timeout;
  11. private class WaitingThread
  12. {
  13. public int Handle;
  14. public ManualResetEvent Event;
  15. public WaitingThread(int Handle, ManualResetEvent Event)
  16. {
  17. this.Handle = Handle;
  18. this.Event = Event;
  19. }
  20. }
  21. private ConcurrentQueue<WaitingThread> WaitingThreads;
  22. public CondVar(AMemory Memory, long CondVarAddress, long Timeout)
  23. {
  24. this.Memory = Memory;
  25. this.CondVarAddress = CondVarAddress;
  26. this.Timeout = Timeout;
  27. WaitingThreads = new ConcurrentQueue<WaitingThread>();
  28. }
  29. public void WaitForSignal(int ThreadHandle)
  30. {
  31. int Count = Memory.ReadInt32(CondVarAddress);
  32. if (Count <= 0)
  33. {
  34. return;
  35. }
  36. Memory.WriteInt32(CondVarAddress, Count - 1);
  37. ManualResetEvent Event = new ManualResetEvent(false);
  38. WaitingThreads.Enqueue(new WaitingThread(ThreadHandle, Event));
  39. if (Timeout != -1)
  40. {
  41. Event.WaitOne((int)(Timeout / 1000000));
  42. }
  43. else
  44. {
  45. Event.WaitOne();
  46. }
  47. }
  48. public void SetSignal(int Count)
  49. {
  50. if (Count == -1)
  51. {
  52. while (WaitingThreads.TryDequeue(out WaitingThread Thread))
  53. {
  54. Thread.Event.Set();
  55. }
  56. Memory.WriteInt32(CondVarAddress, WaitingThreads.Count);
  57. }
  58. else
  59. {
  60. //TODO: Threads with the highest priority needs to be signaled first.
  61. if (WaitingThreads.TryDequeue(out WaitingThread Thread))
  62. {
  63. Thread.Event.Set();
  64. }
  65. Memory.WriteInt32(CondVarAddress, Count);
  66. }
  67. }
  68. }
  69. }