| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using Ryujinx.Horizon.Sdk.OsTypes;
- using Ryujinx.Horizon.Sdk.Sf.Cmif;
- using Ryujinx.Horizon.Sdk.Sm;
- using System;
- using System.Collections.Generic;
- using System.Numerics;
- namespace Ryujinx.Horizon.Sdk.Sf.Hipc
- {
- class ServerManager : ServerManagerBase, IDisposable
- {
- private readonly SmApi _sm;
- private readonly int _pointerBufferSize;
- private readonly bool _canDeferInvokeRequest;
- private readonly int _maxSessions;
- private ulong _pointerBuffersBaseAddress;
- private ulong _savedMessagesBaseAddress;
- private readonly object _resourceLock;
- private readonly ulong[] _sessionAllocationBitmap;
- private readonly HashSet<ServerSession> _sessions;
- private readonly HashSet<Server> _servers;
- public ServerManager(HeapAllocator allocator, SmApi sm, int maxPorts, ManagerOptions options, int maxSessions) : base(sm, options)
- {
- _sm = sm;
- _pointerBufferSize = options.PointerBufferSize;
- _canDeferInvokeRequest = options.CanDeferInvokeRequest;
- _maxSessions = maxSessions;
- if (allocator != null)
- {
- _pointerBuffersBaseAddress = allocator.Allocate((ulong)maxSessions * (ulong)options.PointerBufferSize);
- if (options.CanDeferInvokeRequest)
- {
- _savedMessagesBaseAddress = allocator.Allocate((ulong)maxSessions * (ulong)Api.TlsMessageBufferSize);
- }
- }
- _resourceLock = new object();
- _sessionAllocationBitmap = new ulong[(maxSessions + 63) / 64];
- _sessions = new HashSet<ServerSession>();
- _servers = new HashSet<Server>();
- }
- private PointerAndSize GetObjectBySessionIndex(ServerSession session, ulong baseAddress, ulong size)
- {
- return new PointerAndSize(baseAddress + (ulong)session.SessionIndex * size, size);
- }
- protected override ServerSession AllocateSession(int sessionHandle, ServiceObjectHolder obj)
- {
- int sessionIndex = -1;
- lock (_resourceLock)
- {
- if (_sessions.Count >= _maxSessions)
- {
- return null;
- }
- for (int i = 0; i <_sessionAllocationBitmap.Length; i++)
- {
- ref ulong mask = ref _sessionAllocationBitmap[i];
- if (mask != ulong.MaxValue)
- {
- int bit = BitOperations.TrailingZeroCount(~mask);
- sessionIndex = i * 64 + bit;
- mask |= 1UL << bit;
- break;
- }
- }
- if (sessionIndex == -1)
- {
- return null;
- }
- ServerSession session = new(sessionIndex, sessionHandle, obj);
- _sessions.Add(session);
- return session;
- }
- }
- protected override void FreeSession(ServerSession session)
- {
- if (session.ServiceObjectHolder.ServiceObject is IDisposable disposableObj)
- {
- disposableObj.Dispose();
- }
- lock (_resourceLock)
- {
- _sessionAllocationBitmap[session.SessionIndex / 64] &= ~(1UL << (session.SessionIndex & 63));
- _sessions.Remove(session);
- }
- }
- protected override Server AllocateServer(
- int portIndex,
- int portHandle,
- ServiceName name,
- bool managed,
- ServiceObjectHolder staticHoder)
- {
- lock (_resourceLock)
- {
- Server server = new(portIndex, portHandle, name, managed, staticHoder);
- _servers.Add(server);
- return server;
- }
- }
- protected override void DestroyServer(Server server)
- {
- lock (_resourceLock)
- {
- server.UnlinkFromMultiWaitHolder();
- Os.FinalizeMultiWaitHolder(server);
- if (server.Managed)
- {
- // We should AbortOnFailure, but sometimes SM is already gone when this is called,
- // so let's just ignore potential errors.
- _sm.UnregisterService(server.Name);
- HorizonStatic.Syscall.CloseHandle(server.PortHandle);
- }
- _servers.Remove(server);
- }
- }
- protected override PointerAndSize GetSessionPointerBuffer(ServerSession session)
- {
- if (_pointerBufferSize > 0)
- {
- return GetObjectBySessionIndex(session, _pointerBuffersBaseAddress, (ulong)_pointerBufferSize);
- }
- else
- {
- return PointerAndSize.Empty;
- }
- }
- protected override PointerAndSize GetSessionSavedMessageBuffer(ServerSession session)
- {
- if (_canDeferInvokeRequest)
- {
- return GetObjectBySessionIndex(session, _savedMessagesBaseAddress, Api.TlsMessageBufferSize);
- }
- else
- {
- return PointerAndSize.Empty;
- }
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- lock (_resourceLock)
- {
- ServerSession[] sessionsToClose = new ServerSession[_sessions.Count];
- _sessions.CopyTo(sessionsToClose);
- foreach (ServerSession session in sessionsToClose)
- {
- CloseSessionImpl(session);
- }
- Server[] serversToClose = new Server[_servers.Count];
- _servers.CopyTo(serversToClose);
- foreach (Server server in serversToClose)
- {
- DestroyServer(server);
- }
- }
- }
- }
- public void Dispose()
- {
- Dispose(true);
- }
- }
- }
|