KHandleTable.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System;
  2. namespace Ryujinx.HLE.HOS.Kernel
  3. {
  4. class KHandleTable
  5. {
  6. private const int SelfThreadHandle = (0x1ffff << 15) | 0;
  7. private const int SelfProcessHandle = (0x1ffff << 15) | 1;
  8. private Horizon _system;
  9. private KHandleEntry[] _table;
  10. private KHandleEntry _tableHead;
  11. private KHandleEntry _nextFreeEntry;
  12. private int _activeSlotsCount;
  13. private int _size;
  14. private ushort _idCounter;
  15. public KHandleTable(Horizon system)
  16. {
  17. _system = system;
  18. }
  19. public KernelResult Initialize(int size)
  20. {
  21. if ((uint)size > 1024)
  22. {
  23. return KernelResult.OutOfMemory;
  24. }
  25. if (size < 1)
  26. {
  27. size = 1024;
  28. }
  29. _size = size;
  30. _idCounter = 1;
  31. _table = new KHandleEntry[size];
  32. _tableHead = new KHandleEntry(0);
  33. KHandleEntry entry = _tableHead;
  34. for (int index = 0; index < size; index++)
  35. {
  36. _table[index] = entry;
  37. entry.Next = new KHandleEntry(index + 1);
  38. entry = entry.Next;
  39. }
  40. _table[size - 1].Next = null;
  41. _nextFreeEntry = _tableHead;
  42. return KernelResult.Success;
  43. }
  44. public KernelResult GenerateHandle(object obj, out int handle)
  45. {
  46. handle = 0;
  47. lock (_table)
  48. {
  49. if (_activeSlotsCount >= _size)
  50. {
  51. return KernelResult.HandleTableFull;
  52. }
  53. KHandleEntry entry = _nextFreeEntry;
  54. _nextFreeEntry = entry.Next;
  55. entry.Obj = obj;
  56. entry.HandleId = _idCounter;
  57. _activeSlotsCount++;
  58. handle = (int)((_idCounter << 15) & 0xffff8000) | entry.Index;
  59. if ((short)(_idCounter + 1) >= 0)
  60. {
  61. _idCounter++;
  62. }
  63. else
  64. {
  65. _idCounter = 1;
  66. }
  67. }
  68. return KernelResult.Success;
  69. }
  70. public bool CloseHandle(int handle)
  71. {
  72. if ((handle >> 30) != 0 ||
  73. handle == SelfThreadHandle ||
  74. handle == SelfProcessHandle)
  75. {
  76. return false;
  77. }
  78. int index = (handle >> 0) & 0x7fff;
  79. int handleId = (handle >> 15);
  80. bool result = false;
  81. lock (_table)
  82. {
  83. if (handleId != 0 && index < _size)
  84. {
  85. KHandleEntry entry = _table[index];
  86. if (entry.Obj != null && entry.HandleId == handleId)
  87. {
  88. entry.Obj = null;
  89. entry.Next = _nextFreeEntry;
  90. _nextFreeEntry = entry;
  91. _activeSlotsCount--;
  92. result = true;
  93. }
  94. }
  95. }
  96. return result;
  97. }
  98. public T GetObject<T>(int handle)
  99. {
  100. int index = (handle >> 0) & 0x7fff;
  101. int handleId = (handle >> 15);
  102. lock (_table)
  103. {
  104. if ((handle >> 30) == 0 && handleId != 0)
  105. {
  106. KHandleEntry entry = _table[index];
  107. if (entry.HandleId == handleId && entry.Obj is T obj)
  108. {
  109. return obj;
  110. }
  111. }
  112. }
  113. return default(T);
  114. }
  115. public KThread GetKThread(int handle)
  116. {
  117. if (handle == SelfThreadHandle)
  118. {
  119. return _system.Scheduler.GetCurrentThread();
  120. }
  121. else
  122. {
  123. return GetObject<KThread>(handle);
  124. }
  125. }
  126. public KProcess GetKProcess(int handle)
  127. {
  128. if (handle == SelfProcessHandle)
  129. {
  130. return _system.Scheduler.GetCurrentProcess();
  131. }
  132. else
  133. {
  134. return GetObject<KProcess>(handle);
  135. }
  136. }
  137. public void Destroy()
  138. {
  139. lock (_table)
  140. {
  141. for (int index = 0; index < _size; index++)
  142. {
  143. KHandleEntry entry = _table[index];
  144. if (entry.Obj != null)
  145. {
  146. if (entry.Obj is IDisposable disposableObj)
  147. {
  148. disposableObj.Dispose();
  149. }
  150. entry.Obj = null;
  151. entry.Next = _nextFreeEntry;
  152. _nextFreeEntry = entry;
  153. }
  154. }
  155. }
  156. }
  157. }
  158. }