mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-18 19:26:12 +00:00
meso: Implement ConnectLight
This commit is contained in:
parent
efe7325af3
commit
ad879ca327
12 changed files with 73 additions and 18 deletions
|
@ -35,6 +35,9 @@ MESOSPHERE_AUTO_OBJECT_FW_DECL(InterruptEvent);
|
||||||
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightSession);
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightSession);
|
||||||
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightClientSession);
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightClientSession);
|
||||||
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightServerSession);
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(LightServerSession);
|
||||||
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(Port);
|
||||||
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(ClientPort);
|
||||||
|
MESOSPHERE_AUTO_OBJECT_FW_DECL(ServerPort);
|
||||||
|
|
||||||
class KAutoObject {
|
class KAutoObject {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -97,6 +97,8 @@ class ResultError : public ResultBase<ResultError<module, description>> {
|
||||||
|
|
||||||
#define DEFINE_RESULT(module, name, description) class Result##module##name final : public ResultError<ResultModule::module, description> {}
|
#define DEFINE_RESULT(module, name, description) class Result##module##name final : public ResultError<ResultModule::module, description> {}
|
||||||
|
|
||||||
|
DEFINE_RESULT(Kernel, OutOfSessions, 7);
|
||||||
|
|
||||||
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
|
DEFINE_RESULT(Kernel, InvalidCapabilityDescriptor, 14);
|
||||||
|
|
||||||
DEFINE_RESULT(Kernel, NotImplemented, 33);
|
DEFINE_RESULT(Kernel, NotImplemented, 33);
|
||||||
|
|
|
@ -40,6 +40,15 @@ auto MakeObjectRaw(Args&& ...args)
|
||||||
if constexpr (std::is_base_of_v<ISetAllocated<T>, T>) {
|
if constexpr (std::is_base_of_v<ISetAllocated<T>, T>) {
|
||||||
obj->AddToAllocatedSet();
|
obj->AddToAllocatedSet();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if constexpr (std::is_base_of_v<IClientServerParentTag, T>) {
|
||||||
|
delete &obj->GetClient();
|
||||||
|
delete &obj->GetServer();
|
||||||
|
} else {
|
||||||
|
delete obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = nullptr;
|
||||||
}
|
}
|
||||||
cleanup:
|
cleanup:
|
||||||
if (doReslimitCleanup) {
|
if (doReslimitCleanup) {
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mesosphere/core/KSynchronizationObject.hpp>
|
#include <mesosphere/core/KSynchronizationObject.hpp>
|
||||||
#include <mesosphere/core/util.hpp>
|
|
||||||
#include <mesosphere/core/Result.hpp>
|
|
||||||
#include <mesosphere/interfaces/IClient.hpp>
|
#include <mesosphere/interfaces/IClient.hpp>
|
||||||
#include <mesosphere/threading/KThread.hpp>
|
#include <mesosphere/threading/KThread.hpp>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
{
|
{
|
||||||
|
@ -24,10 +23,14 @@ class KClientPort final :
|
||||||
|
|
||||||
virtual bool IsSignaled() const override;
|
virtual bool IsSignaled() const override;
|
||||||
|
|
||||||
|
std::tuple<Result, SharedPtr<KLightClientSession>> ConnectLight();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class KPort;
|
friend class KPort;
|
||||||
|
|
||||||
std::atomic<int> numSessions{0}, currentCapacity{0}, maxSessions{0};
|
std::atomic<int> numSessions{0};
|
||||||
|
std::atomic<int> peakNumNormalSessions{0};
|
||||||
|
int maxSessions = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
MESOSPHERE_AUTO_OBJECT_DEFINE_INCREF(ClientPort);
|
MESOSPHERE_AUTO_OBJECT_DEFINE_INCREF(ClientPort);
|
||||||
|
|
|
@ -24,7 +24,7 @@ class KLightClientSession final : public KAutoObject, public IClient<KLightSessi
|
||||||
private:
|
private:
|
||||||
friend class KLightSession;
|
friend class KLightSession;
|
||||||
|
|
||||||
KClientPort *parentPort = nullptr;
|
SharedPtr<KClientPort> parentClientPort = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
MESOSPHERE_AUTO_OBJECT_DEFINE_INCREF(LightClientSession);
|
MESOSPHERE_AUTO_OBJECT_DEFINE_INCREF(LightClientSession);
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class KPort;
|
||||||
|
|
||||||
struct LightSessionRequest {
|
struct LightSessionRequest {
|
||||||
s32 cmdId;
|
s32 cmdId;
|
||||||
u32 data[6];
|
u32 data[6];
|
||||||
|
@ -28,7 +30,7 @@ class KLightSession final :
|
||||||
|
|
||||||
virtual ~KLightSession();
|
virtual ~KLightSession();
|
||||||
|
|
||||||
Result Initialize();
|
Result Initialize(KPort *parentPort = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class KLightClientSession;
|
friend class KLightClientSession;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <mesosphere/interfaces/ISetAllocated.hpp>
|
#include <mesosphere/interfaces/ISetAllocated.hpp>
|
||||||
#include <mesosphere/processes/KClientPort.hpp>
|
#include <mesosphere/processes/KClientPort.hpp>
|
||||||
#include <mesosphere/processes/KServerPort.hpp>
|
#include <mesosphere/processes/KServerPort.hpp>
|
||||||
#include <mesosphere/processes/KLightServerSession.hpp>
|
#include <mesosphere/processes/KLightSession.hpp>
|
||||||
|
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
{
|
{
|
||||||
|
@ -23,12 +23,12 @@ class KPort final :
|
||||||
|
|
||||||
Result Initialize(int maxSessions, bool isLight);
|
Result Initialize(int maxSessions, bool isLight);
|
||||||
|
|
||||||
|
Result AddLightServerSession(KLightServerSession &lightServerSession);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class KClientPort;
|
friend class KClientPort;
|
||||||
friend class KServerPort;
|
friend class KServerPort;
|
||||||
|
|
||||||
Result AddServerSession(KLightServerSession &lightServerSession);
|
|
||||||
|
|
||||||
bool isClientAlive = false;
|
bool isClientAlive = false;
|
||||||
bool isServerAlive = false;
|
bool isServerAlive = false;
|
||||||
bool isLight = false;
|
bool isLight = false;
|
||||||
|
|
|
@ -23,7 +23,7 @@ class KServerPort final :
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class KPort;
|
friend class KPort;
|
||||||
Result AddServerSession(KLightServerSession &lightServerSession);
|
Result AddLightServerSession(KLightServerSession &lightServerSession);
|
||||||
|
|
||||||
KLightServerSession::List lightServerSessions{};
|
KLightServerSession::List lightServerSessions{};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <mesosphere/threading/KScopedCriticalSection.hpp>
|
#include <mesosphere/threading/KScopedCriticalSection.hpp>
|
||||||
#include <mesosphere/threading/KThread.hpp>
|
#include <mesosphere/threading/KThread.hpp>
|
||||||
#include <mesosphere/core/KCoreContext.hpp>
|
#include <mesosphere/core/KCoreContext.hpp>
|
||||||
|
#include <mesosphere/core/make_object.hpp>
|
||||||
|
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
{
|
{
|
||||||
|
@ -14,7 +15,30 @@ KClientPort::~KClientPort()
|
||||||
|
|
||||||
bool KClientPort::IsSignaled() const
|
bool KClientPort::IsSignaled() const
|
||||||
{
|
{
|
||||||
return false; // TODO
|
return numSessions.load() < maxSessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<Result, SharedPtr<KLightClientSession>> KClientPort::ConnectLight()
|
||||||
|
{
|
||||||
|
using RetType = std::tuple<Result, SharedPtr<KLightClientSession>>;
|
||||||
|
// Official kernel first checks reslimit then session max count. We will do the opposite.
|
||||||
|
int curCount = numSessions.load();
|
||||||
|
while (curCount < maxSessions || !numSessions.compare_exchange_weak(curCount, curCount + 1));
|
||||||
|
|
||||||
|
if (curCount >= maxSessions) {
|
||||||
|
return RetType{ResultKernelOutOfSessions(), nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [res, serverSession, clientSession] = MakeObject<KLightSession>(parent.get());
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
serverSession.detach(); // Lifetime is now managed my KServerPort session list
|
||||||
|
return RetType{ResultSuccess(), clientSession};
|
||||||
|
} else {
|
||||||
|
if (numSessions.fetch_sub(1) == maxSessions) {
|
||||||
|
NotifyWaiters();
|
||||||
|
}
|
||||||
|
return RetType{res, nullptr};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <mesosphere/processes/KLightSession.hpp>
|
#include <mesosphere/processes/KLightSession.hpp>
|
||||||
|
#include <mesosphere/processes/KPort.hpp>
|
||||||
#include <mesosphere/core/KCoreContext.hpp>
|
#include <mesosphere/core/KCoreContext.hpp>
|
||||||
|
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
|
@ -8,14 +9,24 @@ KLightSession::~KLightSession()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KLightSession::Initialize()
|
Result KLightSession::Initialize(KPort *parentPort)
|
||||||
{
|
{
|
||||||
SetClientServerParent();
|
SetClientServerParent();
|
||||||
isClientAlive = true;
|
isClientAlive = true;
|
||||||
isServerAlive = true;
|
isServerAlive = true;
|
||||||
|
|
||||||
SetResourceOwner(KCoreContext::GetCurrentInstance().GetCurrentProcess());
|
SetResourceOwner(KCoreContext::GetCurrentInstance().GetCurrentProcess());
|
||||||
|
|
||||||
|
if (parentPort == nullptr) {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
} else {
|
||||||
|
// Another difference with official kernel: if adding the session fails, the session isn't added to allocator set (since it'll be deleted right away).
|
||||||
|
Result res = parentPort->AddLightServerSession(server);
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
client.parentClientPort = &parentPort->GetClient();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KLightSession::Terminate(bool fromServer)
|
void KLightSession::Terminate(bool fromServer)
|
||||||
|
|
|
@ -21,13 +21,13 @@ Result KPort::Initialize(int maxSessions, bool isLight)
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KPort::AddServerSession(KLightServerSession &lightServerSession)
|
Result KPort::AddLightServerSession(KLightServerSession &lightServerSession)
|
||||||
{
|
{
|
||||||
KScopedCriticalSection critsec{};
|
KScopedCriticalSection critsec{};
|
||||||
if (isClientAlive || isServerAlive) {
|
if (isClientAlive || isServerAlive) {
|
||||||
return ResultKernelConnectionRefused();
|
return ResultKernelConnectionRefused();
|
||||||
} else {
|
} else {
|
||||||
return server.AddServerSession(lightServerSession);
|
return server.AddLightServerSession(lightServerSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ KServerPort::~KServerPort()
|
||||||
{
|
{
|
||||||
KScopedCriticalSection critsec{};
|
KScopedCriticalSection critsec{};
|
||||||
parent->isServerAlive = false;
|
parent->isServerAlive = false;
|
||||||
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KServerPort::IsSignaled() const
|
bool KServerPort::IsSignaled() const
|
||||||
|
@ -21,7 +22,7 @@ bool KServerPort::IsSignaled() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KServerPort::AddServerSession(KLightServerSession &lightServerSession)
|
Result KServerPort::AddLightServerSession(KLightServerSession &lightServerSession)
|
||||||
{
|
{
|
||||||
KScopedCriticalSection critsec{};
|
KScopedCriticalSection critsec{};
|
||||||
bool wasEmpty = lightServerSessions.empty();
|
bool wasEmpty = lightServerSessions.empty();
|
||||||
|
|
Loading…
Reference in a new issue