mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-09 14:07:58 +00:00
Handle table fixes & additions to makeobject
This commit is contained in:
parent
4a1021f220
commit
c47a9931d9
8 changed files with 126 additions and 17 deletions
107
mesosphere/include/mesosphere/core/make_object.hpp
Normal file
107
mesosphere/include/mesosphere/core/make_object.hpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mesosphere/core/KCoreContext.hpp>
|
||||||
|
#include <mesosphere/threading/KThread.hpp>
|
||||||
|
#include <mesosphere/processes/KProcess.hpp>
|
||||||
|
#include <mesosphere/kresources/KResourceLimit.hpp>
|
||||||
|
#include <mesosphere/interfaces/IClientServerParent.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace mesosphere
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T, typename ...Args>
|
||||||
|
auto MakeObjectRaw(Args&& ...args)
|
||||||
|
{
|
||||||
|
Result res = ResultSuccess;
|
||||||
|
KCoreContext &cctx = KCoreContext::GetCurrentInstance();
|
||||||
|
auto reslimit = cctx.GetCurrentProcess()->GetResourceLimit();
|
||||||
|
bool doReslimitCleanup = false;
|
||||||
|
T *obj = nullptr;
|
||||||
|
if constexpr (std::is_base_of_v<ILimitedResource<T>, T>) {
|
||||||
|
if (reslimit != nullptr) {
|
||||||
|
if (reslimit->Reserve(KResourceLimit::GetCategoryOf<T>(), 1, maxResourceAcqWaitTime)) {
|
||||||
|
doReslimitCleanup = true;
|
||||||
|
} else {
|
||||||
|
return ResultKernelOutOfResource();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj = new T;
|
||||||
|
if (obj == nullptr) {
|
||||||
|
res = ResultKernelResourceExhausted();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = T::Initialize(std::forward<Args>(args)...);
|
||||||
|
if (res.IsSuccess()) {
|
||||||
|
doReslimitCleanup = false;
|
||||||
|
if constexpr (std::is_base_of_v<ISetAllocated<T>, T>) {
|
||||||
|
obj->AddToAllocatedSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
if (doReslimitCleanup) {
|
||||||
|
reslimit->Release(KResourceLimit::GetCategoryOf<T>(), 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::tuple{res, obj};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<!std::is_base_of_v<IClientServerParentTag, T>>, typename ...Args>
|
||||||
|
auto MakeObject(Args&& ...args)
|
||||||
|
{
|
||||||
|
auto [res, obj] = MakeObjectRaw(std::forward<Args>(args)...);
|
||||||
|
return std::tuple{res, SharedPtr{obj}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_base_of_v<IClientServerParentTag, T>>, typename ...Args>
|
||||||
|
auto MakeObject(Args&& ...args)
|
||||||
|
{
|
||||||
|
auto [res, obj] = MakeObjectRaw(std::forward<Args>(args)...);
|
||||||
|
return res.IsSuccess() ? std::tuple{res, SharedPtr{&obj.GetServer()}, SharedPtr{&obj.GetClient()}} : std::tuple{res, nullptr, nullptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<!std::is_base_of_v<IClientServerParentTag, T>>, typename ...Args>
|
||||||
|
auto MakeObjectWithHandle(Args&& ...args)
|
||||||
|
{
|
||||||
|
KCoreContext &cctx = KCoreContext::GetCurrentInstance();
|
||||||
|
KProcess *currentProcess = cctx.GetCurrentProcess();
|
||||||
|
KHandleTable &tbl = currentProcess->GetHandleTable();
|
||||||
|
|
||||||
|
auto [res, obj] = MakeObjectRaw(std::forward<Args>(args)...);
|
||||||
|
if (res.IsFailure()) {
|
||||||
|
return std::tuple{res, Handle{}};
|
||||||
|
}
|
||||||
|
|
||||||
|
return tbl.Generate(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = std::enable_if_t<std::is_base_of_v<IClientServerParentTag, T>>, typename ...Args>
|
||||||
|
auto MakeObjectWithHandle(Args&& ...args)
|
||||||
|
{
|
||||||
|
KCoreContext &cctx = KCoreContext::GetCurrentInstance();
|
||||||
|
KProcess *currentProcess = cctx.GetCurrentProcess();
|
||||||
|
KHandleTable &tbl = currentProcess->GetHandleTable();
|
||||||
|
|
||||||
|
auto [res, obj] = MakeObjectRaw(std::forward<Args>(args)...);
|
||||||
|
if (res.IsFailure()) {
|
||||||
|
return std::tuple{res, Handle{}, Handle{}};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [res2, serverHandle] = tbl.Generate(&obj.GetServer());
|
||||||
|
if (res2.IsSuccess()) {
|
||||||
|
auto [res3, clientHandle] = tbl.Generate(&obj.GetClient());
|
||||||
|
if (res3.IsSuccess()) {
|
||||||
|
return std::tuple{res3, serverHandle, clientHandle};
|
||||||
|
} else {
|
||||||
|
tbl.Close(serverHandle);
|
||||||
|
return std::tuple{res3, Handle{}, Handle{}};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return std::tuple{res2, Handle{}, Handle{}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ class IClient : public IClientTag {
|
||||||
parent->HandleClientDestroyed();
|
parent->HandleClientDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
ParentClass *GetParent() const { return parent; }
|
const SharedPtr<Parent>& GetParent() const { return parent; }
|
||||||
|
|
||||||
void SetParent(SharedPtr<Parent> parent)
|
void SetParent(SharedPtr<Parent> parent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,6 +25,9 @@ class IClientServerParent : public IClientServerParentTag {
|
||||||
server.SetParentAndClient(par, &client);
|
server.SetParentAndClient(par, &client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientClass &GetClient() { return client; }
|
||||||
|
ServerClass &GetServer() { return server; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
ClientClass client{};
|
ClientClass client{};
|
||||||
|
|
|
@ -23,7 +23,7 @@ class IServer : public IServerTag {
|
||||||
parent->HandleServerDestroyed();
|
parent->HandleServerDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
ParentClass *GetParent() const { return parent; }
|
const SharedPtr<Parent> &GetParent() const { return parent; }
|
||||||
|
|
||||||
void SetParentAndClient(SharedPtr<Parent> parent, SharedPtr<Client> client)
|
void SetParentAndClient(SharedPtr<Parent> parent, SharedPtr<Client> client)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,7 +25,6 @@ class ISetAllocated : public KObjectAllocator<Derived>::AllocatedSetHookType
|
||||||
allocator.GetSlabHeap().deallocate((Derived *)ptr);
|
allocator.GetSlabHeap().deallocate((Derived *)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
void AddToAllocatedSet() noexcept
|
void AddToAllocatedSet() noexcept
|
||||||
{
|
{
|
||||||
Derived *d = (Derived *)this;
|
Derived *d = (Derived *)this;
|
||||||
|
@ -33,6 +32,7 @@ class ISetAllocated : public KObjectAllocator<Derived>::AllocatedSetHookType
|
||||||
isRegisteredToAllocator = true;
|
isRegisteredToAllocator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
void RemoveFromAllocatedSet() noexcept
|
void RemoveFromAllocatedSet() noexcept
|
||||||
{
|
{
|
||||||
Derived *d = (Derived *)this;
|
Derived *d = (Derived *)this;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mesosphere/core/KAutoObject.hpp>
|
#include <mesosphere/core/KAutoObject.hpp>
|
||||||
#include <mesosphere/arch/KSpinLock.hpp>
|
#include <mesosphere/arch/KSpinLock.hpp>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
namespace mesosphere
|
namespace mesosphere
|
||||||
{
|
{
|
||||||
|
@ -35,10 +36,10 @@ class KHandleTable final {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Generate(Handle &out, SharedPtr<KAutoObject> obj);
|
std::tuple<Result, Handle> Generate(SharedPtr<KAutoObject> obj);
|
||||||
|
|
||||||
/// For deferred-init
|
/// For deferred-init
|
||||||
bool Set(SharedPtr<KAutoObject> obj, Handle handle);
|
Result Set(SharedPtr<KAutoObject> obj, Handle handle);
|
||||||
|
|
||||||
bool Close(Handle handle);
|
bool Close(Handle handle);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
|
@ -23,6 +23,8 @@ class KProcess : public KAutoObject {
|
||||||
|
|
||||||
const SharedPtr<KResourceLimit> &GetResourceLimit() const { return reslimit; }
|
const SharedPtr<KResourceLimit> &GetResourceLimit() const { return reslimit; }
|
||||||
|
|
||||||
|
KHandleTable &GetHandleTable() { return handleTable; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KThread *lastThreads[MAX_CORES]{nullptr};
|
KThread *lastThreads[MAX_CORES]{nullptr};
|
||||||
ulong lastIdleSelectionCount[MAX_CORES]{0};
|
ulong lastIdleSelectionCount[MAX_CORES]{0};
|
||||||
|
|
|
@ -63,13 +63,13 @@ bool KHandleTable::Close(Handle handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KHandleTable::Generate(Handle &out, SharedPtr<KAutoObject> obj)
|
std::tuple<Result, Handle> KHandleTable::Generate(SharedPtr<KAutoObject> obj)
|
||||||
{
|
{
|
||||||
// Note: nullptr is accepted, for deferred-init.
|
// Note: nullptr is accepted, for deferred-init.
|
||||||
|
|
||||||
std::scoped_lock guard{spinlock};
|
std::scoped_lock guard{spinlock};
|
||||||
if (numActive >= capacity) {
|
if (numActive >= capacity) {
|
||||||
return false; // caller should return 0xD201
|
return {ResultKernelOutOfHandles(), Handle{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get/allocate the entry
|
// Get/allocate the entry
|
||||||
|
@ -80,24 +80,20 @@ bool KHandleTable::Generate(Handle &out, SharedPtr<KAutoObject> obj)
|
||||||
e->id = idCounter;
|
e->id = idCounter;
|
||||||
e->object = std::move(obj);
|
e->object = std::move(obj);
|
||||||
|
|
||||||
out.index = index;
|
|
||||||
out.id = e->id;
|
|
||||||
out.isAlias = false;
|
|
||||||
|
|
||||||
size = ++numActive > size ? numActive : size;
|
size = ++numActive > size ? numActive : size;
|
||||||
idCounter = idCounter == 0x7FFF ? 1 : idCounter + 1;
|
idCounter = idCounter == 0x7FFF ? 1 : idCounter + 1;
|
||||||
|
|
||||||
return true;
|
return {ResultSuccess(), Handle{index, e->id, false}};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KHandleTable::Set(SharedPtr<KAutoObject> obj, Handle handle)
|
Result KHandleTable::Set(SharedPtr<KAutoObject> obj, Handle handle)
|
||||||
{
|
{
|
||||||
if (!handle.IsAliasOrFree() && IsValid(handle)) {
|
if (!handle.IsAliasOrFree() && IsValid(handle)) {
|
||||||
std::scoped_lock guard{spinlock};
|
std::scoped_lock guard{spinlock};
|
||||||
entries[handle.index].object = std::move(obj);
|
entries[handle.index].object = std::move(obj);
|
||||||
return true;
|
return ResultSuccess();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return ResultKernelInvalidHandle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue