NvHostSyncPt.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. namespace Ryujinx.HLE.HOS.Services.Nv.NvHostCtrl
  6. {
  7. class NvHostSyncpt
  8. {
  9. public const int SyncptsCount = 192;
  10. private int[] _counterMin;
  11. private int[] _counterMax;
  12. private long _eventMask;
  13. private ConcurrentDictionary<EventWaitHandle, int> _waiters;
  14. public NvHostSyncpt()
  15. {
  16. _counterMin = new int[SyncptsCount];
  17. _counterMax = new int[SyncptsCount];
  18. _waiters = new ConcurrentDictionary<EventWaitHandle, int>();
  19. }
  20. public int GetMin(int id)
  21. {
  22. return _counterMin[id];
  23. }
  24. public int GetMax(int id)
  25. {
  26. return _counterMax[id];
  27. }
  28. public int Increment(int id)
  29. {
  30. if (((_eventMask >> id) & 1) != 0)
  31. {
  32. Interlocked.Increment(ref _counterMax[id]);
  33. }
  34. return IncrementMin(id);
  35. }
  36. public int IncrementMin(int id)
  37. {
  38. int value = Interlocked.Increment(ref _counterMin[id]);
  39. WakeUpWaiters(id, value);
  40. return value;
  41. }
  42. public int IncrementMax(int id)
  43. {
  44. return Interlocked.Increment(ref _counterMax[id]);
  45. }
  46. public void AddWaiter(int threshold, EventWaitHandle waitEvent)
  47. {
  48. if (!_waiters.TryAdd(waitEvent, threshold))
  49. {
  50. throw new InvalidOperationException();
  51. }
  52. }
  53. public bool RemoveWaiter(EventWaitHandle waitEvent)
  54. {
  55. return _waiters.TryRemove(waitEvent, out _);
  56. }
  57. private void WakeUpWaiters(int id, int newValue)
  58. {
  59. foreach (KeyValuePair<EventWaitHandle, int> kv in _waiters)
  60. {
  61. if (MinCompare(id, newValue, _counterMax[id], kv.Value))
  62. {
  63. kv.Key.Set();
  64. _waiters.TryRemove(kv.Key, out _);
  65. }
  66. }
  67. }
  68. public bool MinCompare(int id, int threshold)
  69. {
  70. return MinCompare(id, _counterMin[id], _counterMax[id], threshold);
  71. }
  72. private bool MinCompare(int id, int min, int max, int threshold)
  73. {
  74. int minDiff = min - threshold;
  75. int maxDiff = max - threshold;
  76. if (((_eventMask >> id) & 1) != 0)
  77. {
  78. return minDiff >= 0;
  79. }
  80. else
  81. {
  82. return (uint)maxDiff >= (uint)minDiff;
  83. }
  84. }
  85. }
  86. }