KProcessHandleTable.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System;
  2. namespace Ryujinx.HLE.HOS.Kernel
  3. {
  4. class KProcessHandleTable
  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. private object LockObj;
  16. public KProcessHandleTable(Horizon System, int Size = 1024)
  17. {
  18. this.System = System;
  19. this.Size = Size;
  20. IdCounter = 1;
  21. Table = new KHandleEntry[Size];
  22. TableHead = new KHandleEntry(0);
  23. KHandleEntry Entry = TableHead;
  24. for (int Index = 0; Index < Size; Index++)
  25. {
  26. Table[Index] = Entry;
  27. Entry.Next = new KHandleEntry(Index + 1);
  28. Entry = Entry.Next;
  29. }
  30. Table[Size - 1].Next = null;
  31. NextFreeEntry = TableHead;
  32. LockObj = new object();
  33. }
  34. public KernelResult GenerateHandle(object Obj, out int Handle)
  35. {
  36. Handle = 0;
  37. lock (LockObj)
  38. {
  39. if (ActiveSlotsCount >= Size)
  40. {
  41. return KernelResult.HandleTableFull;
  42. }
  43. KHandleEntry Entry = NextFreeEntry;
  44. NextFreeEntry = Entry.Next;
  45. Entry.Obj = Obj;
  46. Entry.HandleId = IdCounter;
  47. ActiveSlotsCount++;
  48. Handle = (int)((IdCounter << 15) & (uint)0xffff8000) | Entry.Index;
  49. if ((short)(IdCounter + 1) >= 0)
  50. {
  51. IdCounter++;
  52. }
  53. else
  54. {
  55. IdCounter = 1;
  56. }
  57. }
  58. return KernelResult.Success;
  59. }
  60. public bool CloseHandle(int Handle)
  61. {
  62. if ((Handle >> 30) != 0 ||
  63. Handle == SelfThreadHandle ||
  64. Handle == SelfProcessHandle)
  65. {
  66. return false;
  67. }
  68. int Index = (Handle >> 0) & 0x7fff;
  69. int HandleId = (Handle >> 15);
  70. bool Result = false;
  71. lock (LockObj)
  72. {
  73. if (HandleId != 0 && Index < Size)
  74. {
  75. KHandleEntry Entry = Table[Index];
  76. if (Entry.Obj != null && Entry.HandleId == HandleId)
  77. {
  78. Entry.Obj = null;
  79. Entry.Next = NextFreeEntry;
  80. NextFreeEntry = Entry;
  81. ActiveSlotsCount--;
  82. Result = true;
  83. }
  84. }
  85. }
  86. return Result;
  87. }
  88. public T GetObject<T>(int Handle)
  89. {
  90. int Index = (Handle >> 0) & 0x7fff;
  91. int HandleId = (Handle >> 15);
  92. lock (LockObj)
  93. {
  94. if ((Handle >> 30) == 0 && HandleId != 0)
  95. {
  96. KHandleEntry Entry = Table[Index];
  97. if (Entry.HandleId == HandleId && Entry.Obj is T Obj)
  98. {
  99. return Obj;
  100. }
  101. }
  102. }
  103. return default(T);
  104. }
  105. public KThread GetKThread(int Handle)
  106. {
  107. if (Handle == SelfThreadHandle)
  108. {
  109. return System.Scheduler.GetCurrentThread();
  110. }
  111. else
  112. {
  113. return GetObject<KThread>(Handle);
  114. }
  115. }
  116. public void Destroy()
  117. {
  118. lock (LockObj)
  119. {
  120. for (int Index = 0; Index < Size; Index++)
  121. {
  122. KHandleEntry Entry = Table[Index];
  123. if (Entry.Obj != null)
  124. {
  125. if (Entry.Obj is IDisposable DisposableObj)
  126. {
  127. DisposableObj.Dispose();
  128. }
  129. Entry.Obj = null;
  130. Entry.Next = NextFreeEntry;
  131. NextFreeEntry = Entry;
  132. }
  133. }
  134. }
  135. }
  136. }
  137. }