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. this.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. this.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) & (uint)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. }