Move solution and projects to src
This commit is contained in:
parent
cd124bda58
commit
cee7121058
3466 changed files with 55 additions and 55 deletions
10
src/Ryujinx.HLE/HOS/Kernel/Ipc/ChannelState.cs
Normal file
10
src/Ryujinx.HLE/HOS/Kernel/Ipc/ChannelState.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
enum ChannelState
|
||||
{
|
||||
NotInitialized,
|
||||
Open,
|
||||
ClientDisconnected,
|
||||
ServerDisconnected
|
||||
}
|
||||
}
|
20
src/Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptor.cs
Normal file
20
src/Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptor.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KBufferDescriptor
|
||||
{
|
||||
public ulong ClientAddress { get; }
|
||||
public ulong ServerAddress { get; }
|
||||
public ulong Size { get; }
|
||||
public MemoryState State { get; }
|
||||
|
||||
public KBufferDescriptor(ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
ClientAddress = src;
|
||||
ServerAddress = dst;
|
||||
Size = size;
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
}
|
217
src/Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptorTable.cs
Normal file
217
src/Ryujinx.HLE/HOS/Kernel/Ipc/KBufferDescriptorTable.cs
Normal file
|
@ -0,0 +1,217 @@
|
|||
using Ryujinx.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KBufferDescriptorTable
|
||||
{
|
||||
private const int MaxInternalBuffersCount = 8;
|
||||
|
||||
private List<KBufferDescriptor> _sendBufferDescriptors;
|
||||
private List<KBufferDescriptor> _receiveBufferDescriptors;
|
||||
private List<KBufferDescriptor> _exchangeBufferDescriptors;
|
||||
|
||||
public KBufferDescriptorTable()
|
||||
{
|
||||
_sendBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_receiveBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
_exchangeBufferDescriptors = new List<KBufferDescriptor>(MaxInternalBuffersCount);
|
||||
}
|
||||
|
||||
public Result AddSendBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
return Add(_sendBufferDescriptors, src, dst, size, state);
|
||||
}
|
||||
|
||||
public Result AddReceiveBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
return Add(_receiveBufferDescriptors, src, dst, size, state);
|
||||
}
|
||||
|
||||
public Result AddExchangeBuffer(ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
return Add(_exchangeBufferDescriptors, src, dst, size, state);
|
||||
}
|
||||
|
||||
private Result Add(List<KBufferDescriptor> list, ulong src, ulong dst, ulong size, MemoryState state)
|
||||
{
|
||||
if (list.Count < MaxInternalBuffersCount)
|
||||
{
|
||||
list.Add(new KBufferDescriptor(src, dst, size, state));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return KernelResult.OutOfMemory;
|
||||
}
|
||||
|
||||
public Result CopyBuffersToClient(KPageTableBase memoryManager)
|
||||
{
|
||||
Result result = CopyToClient(memoryManager, _receiveBufferDescriptors);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return CopyToClient(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result CopyToClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor desc in list)
|
||||
{
|
||||
MemoryState stateMask;
|
||||
|
||||
switch (desc.State)
|
||||
{
|
||||
case MemoryState.IpcBuffer0: stateMask = MemoryState.IpcSendAllowedType0; break;
|
||||
case MemoryState.IpcBuffer1: stateMask = MemoryState.IpcSendAllowedType1; break;
|
||||
case MemoryState.IpcBuffer3: stateMask = MemoryState.IpcSendAllowedType3; break;
|
||||
|
||||
default: return KernelResult.InvalidCombination;
|
||||
}
|
||||
|
||||
MemoryAttribute attributeMask = MemoryAttribute.Borrowed | MemoryAttribute.Uncached;
|
||||
|
||||
if (desc.State == MemoryState.IpcBuffer0)
|
||||
{
|
||||
attributeMask |= MemoryAttribute.DeviceMapped;
|
||||
}
|
||||
|
||||
ulong clientAddrTruncated = BitUtils.AlignDown<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
|
||||
ulong clientAddrRounded = BitUtils.AlignUp<ulong>(desc.ClientAddress, KPageTableBase.PageSize);
|
||||
|
||||
// Check if address is not aligned, in this case we need to perform 2 copies.
|
||||
if (clientAddrTruncated != clientAddrRounded)
|
||||
{
|
||||
ulong copySize = clientAddrRounded - desc.ClientAddress;
|
||||
|
||||
if (copySize > desc.Size)
|
||||
{
|
||||
copySize = desc.Size;
|
||||
}
|
||||
|
||||
Result result = memoryManager.CopyDataFromCurrentProcess(
|
||||
desc.ClientAddress,
|
||||
copySize,
|
||||
stateMask,
|
||||
stateMask,
|
||||
KMemoryPermission.ReadAndWrite,
|
||||
attributeMask,
|
||||
MemoryAttribute.None,
|
||||
desc.ServerAddress);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ulong clientEndAddr = desc.ClientAddress + desc.Size;
|
||||
ulong serverEndAddr = desc.ServerAddress + desc.Size;
|
||||
|
||||
ulong clientEndAddrTruncated = BitUtils.AlignDown<ulong>(clientEndAddr, (ulong)KPageTableBase.PageSize);
|
||||
ulong clientEndAddrRounded = BitUtils.AlignUp<ulong>(clientEndAddr, KPageTableBase.PageSize);
|
||||
ulong serverEndAddrTruncated = BitUtils.AlignDown<ulong>(serverEndAddr, (ulong)KPageTableBase.PageSize);
|
||||
|
||||
if (clientEndAddrTruncated < clientEndAddrRounded &&
|
||||
(clientAddrTruncated == clientAddrRounded || clientAddrTruncated < clientEndAddrTruncated))
|
||||
{
|
||||
Result result = memoryManager.CopyDataFromCurrentProcess(
|
||||
clientEndAddrTruncated,
|
||||
clientEndAddr - clientEndAddrTruncated,
|
||||
stateMask,
|
||||
stateMask,
|
||||
KMemoryPermission.ReadAndWrite,
|
||||
attributeMask,
|
||||
MemoryAttribute.None,
|
||||
serverEndAddrTruncated);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result UnmapServerBuffers(KPageTableBase memoryManager)
|
||||
{
|
||||
Result result = UnmapServer(memoryManager, _sendBufferDescriptors);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = UnmapServer(memoryManager, _receiveBufferDescriptors);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return UnmapServer(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result UnmapServer(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor descriptor in list)
|
||||
{
|
||||
Result result = memoryManager.UnmapNoAttributeIfStateEquals(
|
||||
descriptor.ServerAddress,
|
||||
descriptor.Size,
|
||||
descriptor.State);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result RestoreClientBuffers(KPageTableBase memoryManager)
|
||||
{
|
||||
Result result = RestoreClient(memoryManager, _sendBufferDescriptors);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = RestoreClient(memoryManager, _receiveBufferDescriptors);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return RestoreClient(memoryManager, _exchangeBufferDescriptors);
|
||||
}
|
||||
|
||||
private Result RestoreClient(KPageTableBase memoryManager, List<KBufferDescriptor> list)
|
||||
{
|
||||
foreach (KBufferDescriptor descriptor in list)
|
||||
{
|
||||
Result result = memoryManager.UnmapIpcRestorePermission(
|
||||
descriptor.ClientAddress,
|
||||
descriptor.Size,
|
||||
descriptor.State);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
}
|
144
src/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs
Normal file
144
src/Ryujinx.HLE/HOS/Kernel/Ipc/KClientPort.cs
Normal file
|
@ -0,0 +1,144 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.Horizon.Common;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KClientPort : KSynchronizationObject
|
||||
{
|
||||
private int _sessionsCount;
|
||||
private readonly int _maxSessions;
|
||||
|
||||
private readonly KPort _parent;
|
||||
|
||||
public bool IsLight => _parent.IsLight;
|
||||
|
||||
public KClientPort(KernelContext context, KPort parent, int maxSessions) : base(context)
|
||||
{
|
||||
_maxSessions = maxSessions;
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
public Result Connect(out KClientSession clientSession)
|
||||
{
|
||||
clientSession = null;
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
if (currentProcess.ResourceLimit != null &&
|
||||
!currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1))
|
||||
{
|
||||
return KernelResult.ResLimitExceeded;
|
||||
}
|
||||
|
||||
if (!IncrementSessionsCount())
|
||||
{
|
||||
currentProcess.ResourceLimit?.Release(LimitableResource.Session, 1);
|
||||
|
||||
return KernelResult.SessionCountExceeded;
|
||||
}
|
||||
|
||||
KSession session = new KSession(KernelContext, this);
|
||||
|
||||
Result result = _parent.EnqueueIncomingSession(session.ServerSession);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
session.ClientSession.DecrementReferenceCount();
|
||||
session.ServerSession.DecrementReferenceCount();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
clientSession = session.ClientSession;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result ConnectLight(out KLightClientSession clientSession)
|
||||
{
|
||||
clientSession = null;
|
||||
|
||||
KProcess currentProcess = KernelStatic.GetCurrentProcess();
|
||||
|
||||
if (currentProcess.ResourceLimit != null &&
|
||||
!currentProcess.ResourceLimit.Reserve(LimitableResource.Session, 1))
|
||||
{
|
||||
return KernelResult.ResLimitExceeded;
|
||||
}
|
||||
|
||||
if (!IncrementSessionsCount())
|
||||
{
|
||||
currentProcess.ResourceLimit?.Release(LimitableResource.Session, 1);
|
||||
|
||||
return KernelResult.SessionCountExceeded;
|
||||
}
|
||||
|
||||
KLightSession session = new KLightSession(KernelContext);
|
||||
|
||||
Result result = _parent.EnqueueIncomingLightSession(session.ServerSession);
|
||||
|
||||
if (result != Result.Success)
|
||||
{
|
||||
session.ClientSession.DecrementReferenceCount();
|
||||
session.ServerSession.DecrementReferenceCount();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
clientSession = session.ClientSession;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool IncrementSessionsCount()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
int currentCount = _sessionsCount;
|
||||
|
||||
if (currentCount < _maxSessions)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _sessionsCount, currentCount + 1, currentCount) == currentCount)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
SignalIfMaximumReached(Interlocked.Decrement(ref _sessionsCount));
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
private void SignalIfMaximumReached(int value)
|
||||
{
|
||||
if (value == _maxSessions)
|
||||
{
|
||||
Signal();
|
||||
}
|
||||
}
|
||||
|
||||
public new static Result RemoveName(KernelContext context, string name)
|
||||
{
|
||||
KAutoObject foundObj = FindNamedObject(context, name);
|
||||
|
||||
if (!(foundObj is KClientPort))
|
||||
{
|
||||
return KernelResult.NotFound;
|
||||
}
|
||||
|
||||
return KAutoObject.RemoveName(context, name);
|
||||
}
|
||||
}
|
||||
}
|
84
src/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs
Normal file
84
src/Ryujinx.HLE/HOS/Kernel/Ipc/KClientSession.cs
Normal file
|
@ -0,0 +1,84 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.Horizon.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KClientSession : KSynchronizationObject
|
||||
{
|
||||
public KProcess CreatorProcess { get; }
|
||||
|
||||
private KSession _parent;
|
||||
|
||||
public ChannelState State { get; set; }
|
||||
|
||||
public KClientPort ParentPort { get; }
|
||||
|
||||
public KClientSession(KernelContext context, KSession parent, KClientPort parentPort) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
ParentPort = parentPort;
|
||||
|
||||
parentPort?.IncrementReferenceCount();
|
||||
|
||||
State = ChannelState.Open;
|
||||
|
||||
CreatorProcess = KernelStatic.GetCurrentProcess();
|
||||
CreatorProcess.IncrementReferenceCount();
|
||||
}
|
||||
|
||||
public Result SendSyncRequest(ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize);
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
currentThread.SignaledObj = null;
|
||||
currentThread.ObjSyncResult = Result.Success;
|
||||
|
||||
Result result = _parent.ServerSession.EnqueueRequest(request);
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
if (result == Result.Success)
|
||||
{
|
||||
result = currentThread.ObjSyncResult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result SendAsyncRequest(KWritableEvent asyncEvent, ulong customCmdBuffAddr = 0, ulong customCmdBuffSize = 0)
|
||||
{
|
||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||
|
||||
KSessionRequest request = new KSessionRequest(currentThread, customCmdBuffAddr, customCmdBuffSize, asyncEvent);
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
Result result = _parent.ServerSession.EnqueueRequest(request);
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void DisconnectFromPort()
|
||||
{
|
||||
if (ParentPort != null)
|
||||
{
|
||||
ParentPort.Disconnect();
|
||||
ParentPort.DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Destroy()
|
||||
{
|
||||
_parent.DisconnectClient();
|
||||
_parent.DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
14
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs
Normal file
14
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightClientSession.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KLightClientSession : KAutoObject
|
||||
{
|
||||
private readonly KLightSession _parent;
|
||||
|
||||
public KLightClientSession(KernelContext context, KLightSession parent) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
14
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs
Normal file
14
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightServerSession.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KLightServerSession : KAutoObject
|
||||
{
|
||||
private readonly KLightSession _parent;
|
||||
|
||||
public KLightServerSession(KernelContext context, KLightSession parent) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
16
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs
Normal file
16
src/Ryujinx.HLE/HOS/Kernel/Ipc/KLightSession.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KLightSession : KAutoObject
|
||||
{
|
||||
public KLightServerSession ServerSession { get; }
|
||||
public KLightClientSession ClientSession { get; }
|
||||
|
||||
public KLightSession(KernelContext context) : base(context)
|
||||
{
|
||||
ServerSession = new KLightServerSession(context, this);
|
||||
ClientSession = new KLightClientSession(context, this);
|
||||
}
|
||||
}
|
||||
}
|
72
src/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs
Normal file
72
src/Ryujinx.HLE/HOS/Kernel/Ipc/KPort.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.Horizon.Common;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KPort : KAutoObject
|
||||
{
|
||||
public KServerPort ServerPort { get; }
|
||||
public KClientPort ClientPort { get; }
|
||||
|
||||
private string _name;
|
||||
|
||||
private ChannelState _state;
|
||||
|
||||
public bool IsLight { get; private set; }
|
||||
|
||||
public KPort(KernelContext context, int maxSessions, bool isLight, string name) : base(context)
|
||||
{
|
||||
ServerPort = new KServerPort(context, this);
|
||||
ClientPort = new KClientPort(context, this, maxSessions);
|
||||
|
||||
IsLight = isLight;
|
||||
_name = name;
|
||||
|
||||
_state = ChannelState.Open;
|
||||
}
|
||||
|
||||
public Result EnqueueIncomingSession(KServerSession session)
|
||||
{
|
||||
Result result;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
if (_state == ChannelState.Open)
|
||||
{
|
||||
ServerPort.EnqueueIncomingSession(session);
|
||||
|
||||
result = Result.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = KernelResult.PortClosed;
|
||||
}
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result EnqueueIncomingLightSession(KLightServerSession session)
|
||||
{
|
||||
Result result;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
if (_state == ChannelState.Open)
|
||||
{
|
||||
ServerPort.EnqueueIncomingLightSession(session);
|
||||
|
||||
result = Result.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = KernelResult.PortClosed;
|
||||
}
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
87
src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs
Normal file
87
src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerPort.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KServerPort : KSynchronizationObject
|
||||
{
|
||||
private readonly LinkedList<KServerSession> _incomingConnections;
|
||||
private readonly LinkedList<KLightServerSession> _lightIncomingConnections;
|
||||
|
||||
private readonly KPort _parent;
|
||||
|
||||
public bool IsLight => _parent.IsLight;
|
||||
|
||||
public KServerPort(KernelContext context, KPort parent) : base(context)
|
||||
{
|
||||
_parent = parent;
|
||||
|
||||
_incomingConnections = new LinkedList<KServerSession>();
|
||||
_lightIncomingConnections = new LinkedList<KLightServerSession>();
|
||||
}
|
||||
|
||||
public void EnqueueIncomingSession(KServerSession session)
|
||||
{
|
||||
AcceptIncomingConnection(_incomingConnections, session);
|
||||
}
|
||||
|
||||
public void EnqueueIncomingLightSession(KLightServerSession session)
|
||||
{
|
||||
AcceptIncomingConnection(_lightIncomingConnections, session);
|
||||
}
|
||||
|
||||
private void AcceptIncomingConnection<T>(LinkedList<T> list, T session)
|
||||
{
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
list.AddLast(session);
|
||||
|
||||
if (list.Count == 1)
|
||||
{
|
||||
Signal();
|
||||
}
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
}
|
||||
|
||||
public KServerSession AcceptIncomingConnection()
|
||||
{
|
||||
return AcceptIncomingConnection(_incomingConnections);
|
||||
}
|
||||
|
||||
public KLightServerSession AcceptIncomingLightConnection()
|
||||
{
|
||||
return AcceptIncomingConnection(_lightIncomingConnections);
|
||||
}
|
||||
|
||||
private T AcceptIncomingConnection<T>(LinkedList<T> list)
|
||||
{
|
||||
T session = default;
|
||||
|
||||
KernelContext.CriticalSection.Enter();
|
||||
|
||||
if (list.Count != 0)
|
||||
{
|
||||
session = list.First.Value;
|
||||
|
||||
list.RemoveFirst();
|
||||
}
|
||||
|
||||
KernelContext.CriticalSection.Leave();
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public override bool IsSignaled()
|
||||
{
|
||||
if (_parent.IsLight)
|
||||
{
|
||||
return _lightIncomingConnections.Count != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _incomingConnections.Count != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1246
src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs
Normal file
1246
src/Ryujinx.HLE/HOS/Kernel/Ipc/KServerSession.cs
Normal file
File diff suppressed because it is too large
Load diff
54
src/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs
Normal file
54
src/Ryujinx.HLE/HOS/Kernel/Ipc/KSession.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KSession : KAutoObject
|
||||
{
|
||||
public KServerSession ServerSession { get; }
|
||||
public KClientSession ClientSession { get; }
|
||||
|
||||
private bool _hasBeenInitialized;
|
||||
|
||||
public KSession(KernelContext context, KClientPort parentPort = null) : base(context)
|
||||
{
|
||||
IncrementReferenceCount();
|
||||
|
||||
ServerSession = new KServerSession(context, this);
|
||||
ClientSession = new KClientSession(context, this, parentPort);
|
||||
|
||||
_hasBeenInitialized = true;
|
||||
}
|
||||
|
||||
public void DisconnectClient()
|
||||
{
|
||||
if (ClientSession.State == ChannelState.Open)
|
||||
{
|
||||
ClientSession.State = ChannelState.ClientDisconnected;
|
||||
|
||||
ServerSession.CancelAllRequestsClientDisconnected();
|
||||
}
|
||||
}
|
||||
|
||||
public void DisconnectServer()
|
||||
{
|
||||
if (ClientSession.State == ChannelState.Open)
|
||||
{
|
||||
ClientSession.State = ChannelState.ServerDisconnected;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Destroy()
|
||||
{
|
||||
if (_hasBeenInitialized)
|
||||
{
|
||||
ClientSession.DisconnectFromPort();
|
||||
|
||||
KProcess creatorProcess = ClientSession.CreatorProcess;
|
||||
|
||||
creatorProcess.ResourceLimit?.Release(LimitableResource.Session, 1);
|
||||
creatorProcess.DecrementReferenceCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
src/Ryujinx.HLE/HOS/Kernel/Ipc/KSessionRequest.cs
Normal file
33
src/Ryujinx.HLE/HOS/Kernel/Ipc/KSessionRequest.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Kernel.Ipc
|
||||
{
|
||||
class KSessionRequest
|
||||
{
|
||||
public KBufferDescriptorTable BufferDescriptorTable { get; }
|
||||
|
||||
public KThread ClientThread { get; }
|
||||
|
||||
public KProcess ServerProcess { get; set; }
|
||||
|
||||
public KWritableEvent AsyncEvent { get; }
|
||||
|
||||
public ulong CustomCmdBuffAddr { get; }
|
||||
public ulong CustomCmdBuffSize { get; }
|
||||
|
||||
public KSessionRequest(
|
||||
KThread clientThread,
|
||||
ulong customCmdBuffAddr,
|
||||
ulong customCmdBuffSize,
|
||||
KWritableEvent asyncEvent = null)
|
||||
{
|
||||
ClientThread = clientThread;
|
||||
CustomCmdBuffAddr = customCmdBuffAddr;
|
||||
CustomCmdBuffSize = customCmdBuffSize;
|
||||
AsyncEvent = asyncEvent;
|
||||
|
||||
BufferDescriptorTable = new KBufferDescriptorTable();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue