KClientPort.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. using Ryujinx.HLE.HOS.Kernel.Common;
  2. using Ryujinx.HLE.HOS.Kernel.Process;
  3. using Ryujinx.HLE.HOS.Services;
  4. namespace Ryujinx.HLE.HOS.Kernel.Ipc
  5. {
  6. class KClientPort : KSynchronizationObject
  7. {
  8. private int _sessionsCount;
  9. private int _currentCapacity;
  10. private int _maxSessions;
  11. private KPort _parent;
  12. public bool IsLight => _parent.IsLight;
  13. private object _countIncLock;
  14. // TODO: Remove that, we need it for now to allow HLE
  15. // SM implementation to work with the new IPC system.
  16. public IpcService Service { get; set; }
  17. public KClientPort(Horizon system, KPort parent, int maxSessions) : base(system)
  18. {
  19. _maxSessions = maxSessions;
  20. _parent = parent;
  21. _countIncLock = new object();
  22. }
  23. public KernelResult Connect(out KClientSession clientSession)
  24. {
  25. clientSession = null;
  26. KProcess currentProcess = System.Scheduler.GetCurrentProcess();
  27. if (currentProcess.ResourceLimit != null &&
  28. !currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1))
  29. {
  30. return KernelResult.ResLimitExceeded;
  31. }
  32. lock (_countIncLock)
  33. {
  34. if (_sessionsCount < _maxSessions)
  35. {
  36. _sessionsCount++;
  37. }
  38. else
  39. {
  40. currentProcess.ResourceLimit?.Release(LimitableResource.Session, 1);
  41. return KernelResult.SessionCountExceeded;
  42. }
  43. if (_currentCapacity < _sessionsCount)
  44. {
  45. _currentCapacity = _sessionsCount;
  46. }
  47. }
  48. KSession session = new KSession(System);
  49. if (Service != null)
  50. {
  51. session.ClientSession.Service = Service;
  52. }
  53. KernelResult result = _parent.EnqueueIncomingSession(session.ServerSession);
  54. if (result != KernelResult.Success)
  55. {
  56. session.ClientSession.DecrementReferenceCount();
  57. session.ServerSession.DecrementReferenceCount();
  58. return result;
  59. }
  60. clientSession = session.ClientSession;
  61. return result;
  62. }
  63. public KernelResult ConnectLight(out KLightClientSession clientSession)
  64. {
  65. clientSession = null;
  66. KProcess currentProcess = System.Scheduler.GetCurrentProcess();
  67. if (currentProcess.ResourceLimit != null &&
  68. !currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1))
  69. {
  70. return KernelResult.ResLimitExceeded;
  71. }
  72. lock (_countIncLock)
  73. {
  74. if (_sessionsCount < _maxSessions)
  75. {
  76. _sessionsCount++;
  77. }
  78. else
  79. {
  80. currentProcess.ResourceLimit?.Release(LimitableResource.Session, 1);
  81. return KernelResult.SessionCountExceeded;
  82. }
  83. }
  84. KLightSession session = new KLightSession(System);
  85. KernelResult result = _parent.EnqueueIncomingLightSession(session.ServerSession);
  86. if (result != KernelResult.Success)
  87. {
  88. session.ClientSession.DecrementReferenceCount();
  89. session.ServerSession.DecrementReferenceCount();
  90. return result;
  91. }
  92. clientSession = session.ClientSession;
  93. return result;
  94. }
  95. public new static KernelResult RemoveName(Horizon system, string name)
  96. {
  97. KAutoObject foundObj = FindNamedObject(system, name);
  98. if (!(foundObj is KClientPort))
  99. {
  100. return KernelResult.NotFound;
  101. }
  102. return KAutoObject.RemoveName(system, name);
  103. }
  104. }
  105. }