mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +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();
|
||||
}
|
||||
|
||||
ParentClass *GetParent() const { return parent; }
|
||||
const SharedPtr<Parent>& GetParent() const { return parent; }
|
||||
|
||||
void SetParent(SharedPtr<Parent> parent)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,9 @@ class IClientServerParent : public IClientServerParentTag {
|
|||
server.SetParentAndClient(par, &client);
|
||||
}
|
||||
|
||||
ClientClass &GetClient() { return client; }
|
||||
ServerClass &GetServer() { return server; }
|
||||
|
||||
protected:
|
||||
|
||||
ClientClass client{};
|
||||
|
|
|
@ -23,7 +23,7 @@ class IServer : public IServerTag {
|
|||
parent->HandleServerDestroyed();
|
||||
}
|
||||
|
||||
ParentClass *GetParent() const { return parent; }
|
||||
const SharedPtr<Parent> &GetParent() const { return parent; }
|
||||
|
||||
void SetParentAndClient(SharedPtr<Parent> parent, SharedPtr<Client> client)
|
||||
{
|
||||
|
|
|
@ -25,7 +25,6 @@ class ISetAllocated : public KObjectAllocator<Derived>::AllocatedSetHookType
|
|||
allocator.GetSlabHeap().deallocate((Derived *)ptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
void AddToAllocatedSet() noexcept
|
||||
{
|
||||
Derived *d = (Derived *)this;
|
||||
|
@ -33,6 +32,7 @@ class ISetAllocated : public KObjectAllocator<Derived>::AllocatedSetHookType
|
|||
isRegisteredToAllocator = true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void RemoveFromAllocatedSet() noexcept
|
||||
{
|
||||
Derived *d = (Derived *)this;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <mesosphere/core/KAutoObject.hpp>
|
||||
#include <mesosphere/arch/KSpinLock.hpp>
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
|
||||
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
|
||||
bool Set(SharedPtr<KAutoObject> obj, Handle handle);
|
||||
Result Set(SharedPtr<KAutoObject> obj, Handle handle);
|
||||
|
||||
bool Close(Handle handle);
|
||||
void Destroy();
|
||||
|
|
|
@ -23,6 +23,8 @@ class KProcess : public KAutoObject {
|
|||
|
||||
const SharedPtr<KResourceLimit> &GetResourceLimit() const { return reslimit; }
|
||||
|
||||
KHandleTable &GetHandleTable() { return handleTable; }
|
||||
|
||||
private:
|
||||
KThread *lastThreads[MAX_CORES]{nullptr};
|
||||
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.
|
||||
|
||||
std::scoped_lock guard{spinlock};
|
||||
if (numActive >= capacity) {
|
||||
return false; // caller should return 0xD201
|
||||
return {ResultKernelOutOfHandles(), Handle{}};
|
||||
}
|
||||
|
||||
// Get/allocate the entry
|
||||
|
@ -80,24 +80,20 @@ bool KHandleTable::Generate(Handle &out, SharedPtr<KAutoObject> obj)
|
|||
e->id = idCounter;
|
||||
e->object = std::move(obj);
|
||||
|
||||
out.index = index;
|
||||
out.id = e->id;
|
||||
out.isAlias = false;
|
||||
|
||||
size = ++numActive > size ? numActive : size;
|
||||
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)) {
|
||||
std::scoped_lock guard{spinlock};
|
||||
entries[handle.index].object = std::move(obj);
|
||||
return true;
|
||||
return ResultSuccess();
|
||||
} else {
|
||||
return false;
|
||||
return ResultKernelInvalidHandle();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue