Handle table fixes & additions to makeobject

This commit is contained in:
TuxSH 2018-11-06 16:00:52 +01:00 committed by Michael Scire
parent 4a1021f220
commit c47a9931d9
8 changed files with 126 additions and 17 deletions

View 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{}};
}
}
}

View file

@ -23,8 +23,8 @@ 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)
{ {
this->parent = std::move(parent); this->parent = std::move(parent);

View file

@ -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{};

View file

@ -22,8 +22,8 @@ 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)
{ {

View file

@ -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;

View file

@ -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();

View file

@ -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};

View file

@ -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();
} }
} }