diff --git a/mesosphere/include/mesosphere/core/make_object.hpp b/mesosphere/include/mesosphere/core/make_object.hpp new file mode 100644 index 000000000..0b154ae7b --- /dev/null +++ b/mesosphere/include/mesosphere/core/make_object.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace mesosphere +{ + +template +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, T>) { + if (reslimit != nullptr) { + if (reslimit->Reserve(KResourceLimit::GetCategoryOf(), 1, maxResourceAcqWaitTime)) { + doReslimitCleanup = true; + } else { + return ResultKernelOutOfResource(); + } + } + } + + obj = new T; + if (obj == nullptr) { + res = ResultKernelResourceExhausted(); + goto cleanup; + } + + res = T::Initialize(std::forward(args)...); + if (res.IsSuccess()) { + doReslimitCleanup = false; + if constexpr (std::is_base_of_v, T>) { + obj->AddToAllocatedSet(); + } + } +cleanup: + if (doReslimitCleanup) { + reslimit->Release(KResourceLimit::GetCategoryOf(), 1, 1); + } + + return std::tuple{res, obj}; +} + +template>, typename ...Args> +auto MakeObject(Args&& ...args) +{ + auto [res, obj] = MakeObjectRaw(std::forward(args)...); + return std::tuple{res, SharedPtr{obj}}; +} + +template>, typename ...Args> +auto MakeObject(Args&& ...args) +{ + auto [res, obj] = MakeObjectRaw(std::forward(args)...); + return res.IsSuccess() ? std::tuple{res, SharedPtr{&obj.GetServer()}, SharedPtr{&obj.GetClient()}} : std::tuple{res, nullptr, nullptr}; +} + +template>, 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)...); + if (res.IsFailure()) { + return std::tuple{res, Handle{}}; + } + + return tbl.Generate(obj); +} + +template>, 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)...); + 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{}}; + } +} + +} \ No newline at end of file diff --git a/mesosphere/include/mesosphere/interfaces/IClient.hpp b/mesosphere/include/mesosphere/interfaces/IClient.hpp index 4e01c7efb..8e891a05a 100644 --- a/mesosphere/include/mesosphere/interfaces/IClient.hpp +++ b/mesosphere/include/mesosphere/interfaces/IClient.hpp @@ -23,8 +23,8 @@ class IClient : public IClientTag { parent->HandleClientDestroyed(); } - ParentClass *GetParent() const { return parent; } - + const SharedPtr& GetParent() const { return parent; } + void SetParent(SharedPtr parent) { this->parent = std::move(parent); diff --git a/mesosphere/include/mesosphere/interfaces/IClientServerParent.hpp b/mesosphere/include/mesosphere/interfaces/IClientServerParent.hpp index 4cb40800a..2a87465dd 100644 --- a/mesosphere/include/mesosphere/interfaces/IClientServerParent.hpp +++ b/mesosphere/include/mesosphere/interfaces/IClientServerParent.hpp @@ -25,6 +25,9 @@ class IClientServerParent : public IClientServerParentTag { server.SetParentAndClient(par, &client); } + ClientClass &GetClient() { return client; } + ServerClass &GetServer() { return server; } + protected: ClientClass client{}; diff --git a/mesosphere/include/mesosphere/interfaces/IServer.hpp b/mesosphere/include/mesosphere/interfaces/IServer.hpp index 15e4e1d55..fc5943a19 100644 --- a/mesosphere/include/mesosphere/interfaces/IServer.hpp +++ b/mesosphere/include/mesosphere/interfaces/IServer.hpp @@ -22,8 +22,8 @@ class IServer : public IServerTag { { parent->HandleServerDestroyed(); } - - ParentClass *GetParent() const { return parent; } + + const SharedPtr &GetParent() const { return parent; } void SetParentAndClient(SharedPtr parent, SharedPtr client) { diff --git a/mesosphere/include/mesosphere/interfaces/ISetAllocated.hpp b/mesosphere/include/mesosphere/interfaces/ISetAllocated.hpp index c3fce4ba9..4b727ec6e 100644 --- a/mesosphere/include/mesosphere/interfaces/ISetAllocated.hpp +++ b/mesosphere/include/mesosphere/interfaces/ISetAllocated.hpp @@ -25,7 +25,6 @@ class ISetAllocated : public KObjectAllocator::AllocatedSetHookType allocator.GetSlabHeap().deallocate((Derived *)ptr); } - protected: void AddToAllocatedSet() noexcept { Derived *d = (Derived *)this; @@ -33,6 +32,7 @@ class ISetAllocated : public KObjectAllocator::AllocatedSetHookType isRegisteredToAllocator = true; } + protected: void RemoveFromAllocatedSet() noexcept { Derived *d = (Derived *)this; diff --git a/mesosphere/include/mesosphere/processes/KHandleTable.hpp b/mesosphere/include/mesosphere/processes/KHandleTable.hpp index 57aef5a92..d096f2ac1 100644 --- a/mesosphere/include/mesosphere/processes/KHandleTable.hpp +++ b/mesosphere/include/mesosphere/processes/KHandleTable.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace mesosphere { @@ -35,10 +36,10 @@ class KHandleTable final { } } - bool Generate(Handle &out, SharedPtr obj); + std::tuple Generate(SharedPtr obj); /// For deferred-init - bool Set(SharedPtr obj, Handle handle); + Result Set(SharedPtr obj, Handle handle); bool Close(Handle handle); void Destroy(); diff --git a/mesosphere/include/mesosphere/processes/KProcess.hpp b/mesosphere/include/mesosphere/processes/KProcess.hpp index 8a5a636ca..109ab62a3 100644 --- a/mesosphere/include/mesosphere/processes/KProcess.hpp +++ b/mesosphere/include/mesosphere/processes/KProcess.hpp @@ -23,6 +23,8 @@ class KProcess : public KAutoObject { const SharedPtr &GetResourceLimit() const { return reslimit; } + KHandleTable &GetHandleTable() { return handleTable; } + private: KThread *lastThreads[MAX_CORES]{nullptr}; ulong lastIdleSelectionCount[MAX_CORES]{0}; diff --git a/mesosphere/source/processes/KHandleTable.cpp b/mesosphere/source/processes/KHandleTable.cpp index 41b01fb23..8ab203dec 100644 --- a/mesosphere/source/processes/KHandleTable.cpp +++ b/mesosphere/source/processes/KHandleTable.cpp @@ -63,13 +63,13 @@ bool KHandleTable::Close(Handle handle) } } -bool KHandleTable::Generate(Handle &out, SharedPtr obj) +std::tuple KHandleTable::Generate(SharedPtr 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 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 obj, Handle handle) +Result KHandleTable::Set(SharedPtr 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(); } }