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();
}
ParentClass *GetParent() const { return parent; }
const SharedPtr<Parent>& GetParent() const { return parent; }
void SetParent(SharedPtr<Parent> parent)
{
this->parent = std::move(parent);

View file

@ -25,6 +25,9 @@ class IClientServerParent : public IClientServerParentTag {
server.SetParentAndClient(par, &client);
}
ClientClass &GetClient() { return client; }
ServerClass &GetServer() { return server; }
protected:
ClientClass client{};

View file

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

View file

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

View file

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

View file

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

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