From ec988c5a993d51d742263db033e886d7b65e3983 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 8 Apr 2021 15:24:22 -0700 Subject: [PATCH] tipc: first draft object allocation logic --- .../stratosphere/sf/sf_object_factory.hpp | 2 +- .../include/stratosphere/tipc.hpp | 3 + .../tipc/impl/tipc_impl_template_base.hpp | 32 +++++++ .../stratosphere/tipc/tipc_allocators.hpp | 86 +++++++++++++++++++ .../stratosphere/tipc/tipc_service_object.hpp | 61 +++++++++++++ .../tipc/tipc_service_object_base.hpp | 53 ++++++++++++ 6 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 libraries/libstratosphere/include/stratosphere/tipc/impl/tipc_impl_template_base.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/tipc/tipc_allocators.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object.hpp create mode 100644 libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object_base.hpp diff --git a/libraries/libstratosphere/include/stratosphere/sf/sf_object_factory.hpp b/libraries/libstratosphere/include/stratosphere/sf/sf_object_factory.hpp index 5e44c2bed..0f59564c7 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/sf_object_factory.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/sf_object_factory.hpp @@ -43,7 +43,7 @@ namespace ams::sf { using Type = Impl; }; - template requires (std::is_abstract::value ) + template requires (std::is_abstract::value) struct UnmanagedEmplaceImplHolderBaseGetter { class Impl2 : public Impl { public: diff --git a/libraries/libstratosphere/include/stratosphere/tipc.hpp b/libraries/libstratosphere/include/stratosphere/tipc.hpp index dc8227750..8102c877d 100644 --- a/libraries/libstratosphere/include/stratosphere/tipc.hpp +++ b/libraries/libstratosphere/include/stratosphere/tipc.hpp @@ -15,4 +15,7 @@ */ #pragma once +#include +#include + #include diff --git a/libraries/libstratosphere/include/stratosphere/tipc/impl/tipc_impl_template_base.hpp b/libraries/libstratosphere/include/stratosphere/tipc/impl/tipc_impl_template_base.hpp new file mode 100644 index 000000000..66bae137c --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/tipc/impl/tipc_impl_template_base.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::tipc::impl { + + template + class ImplTemplateBaseT; + + template + class ImplTemplateBase : public ImplTemplateBaseT { + private: + using BaseImpl = ImplTemplateBaseT; + public: + using BaseImpl::BaseImpl; + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/tipc/tipc_allocators.hpp b/libraries/libstratosphere/include/stratosphere/tipc/tipc_allocators.hpp new file mode 100644 index 000000000..8600499ec --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/tipc/tipc_allocators.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include + +namespace ams::tipc { + + template + concept IsServiceObjectAllocator = requires (T &t) { + { t.Allocate() } -> std::convertible_to; + }; + + template requires IsServiceObject + class SingletonAllocator final { + private: + T m_singleton; + public: + constexpr ALWAYS_INLINE SingletonAllocator() : m_singleton() { /* ... */ } + + ALWAYS_INLINE ServiceObjectBase *Allocate() { return std::addressof(m_singleton); } + }; + + template requires IsServiceObject + class SlabAllocator final : public ServiceObjectDeleter { + private: + struct Entry { + bool used; + util::TypedStorage storage; + }; + private: + os::SdkMutex m_mutex; + Entry m_entries[N]; + public: + constexpr ALWAYS_INLINE SlabAllocator() : m_entries() { /* ... */ } + + ServiceObjectBase *Allocate() { + std::scoped_lock lk(m_mutex); + + for (size_t i = 0; i < N; ++i) { + if (!m_entries[i].used) { + m_entries[i].used = true; + return util::ConstructAt(m_entries[i].storage); + } + } + + AMS_ABORT("Failed to allocate entry in SlabAllocator"); + } + + void Deallocate(ServiceObjectBase *object) { + std::scoped_lock lk(m_mutex); + + for (size_t i = 0; i < N; ++i) { + if (m_entries[i].used && GetPointer(m_entries[i].storage) == object) { + util::DestroyAt(m_entries[i].storage); + m_entries[i].used = false; + return; + } + } + + AMS_ABORT("Failed to deallocate entry in SlabAllocator"); + } + public: + virtual void DeleteServiceObject(ServiceObjectBase *object) override { + return this->Deallocate(object); + } + }; + static_assert(IsServiceObjectAllocator>); + static_assert(IsServiceObjectDeleter>); + +} + diff --git a/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object.hpp b/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object.hpp new file mode 100644 index 000000000..2549a1a83 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object.hpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include + +namespace ams::tipc { + + namespace impl { + + template + class EmplacedImplHolderBaseGetter { + using Type = Impl; + }; + + template + class EmplacedImplHolder { + template + friend class impl::ImplTemplateBaseT; + private: + using Impl2 = typename EmplacedImplHolderBaseGetter::Type; + static_assert(!std::is_abstract::value); + private: + Impl2 m_impl; + private: + template + constexpr explicit EmplacedImplHolder(Args &&... args) : m_impl(std::forward(args)...) { /* ... */ } + public: + static constexpr Impl *GetImplPointer(EmplacedImplHolder *holder) { + return std::addressof(holder->m_impl); + } + }; + + } + + template + class ServiceObject final : public impl::ImplTemplateBase, impl::EmplacedImplHolder> { + private: + using ImplBase = impl::ImplTemplateBase, impl::EmplacedImplHolder>; + public: + using ImplBase::ImplBase; + + constexpr Impl &GetImpl() { return *impl::EmplacedImplHolder::GetImplPointer(this); } + }; + +} + diff --git a/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object_base.hpp b/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object_base.hpp new file mode 100644 index 000000000..f51de8c48 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/tipc/tipc_service_object_base.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::tipc { + + class ServiceObjectBase; + + class ServiceObjectDeleter { + public: + virtual void DeleteServiceObject(ServiceObjectBase *object) = 0; + }; + + template + concept IsServiceObjectDeleter = std::derived_from; + + class ServiceObjectBase { + private: + ServiceObjectDeleter *m_deleter; + public: + constexpr ALWAYS_INLINE ServiceObjectBase() : m_deleter(nullptr) { /* ... */ } + + ALWAYS_INLINE void SetDeleter(ServiceObjectDeleter *deleter) { + m_deleter = deleter; + } + + ALWAYS_INLINE ServiceObjectDeleter *GetDeleter() const { + return m_deleter; + } + + virtual ~ServiceObjectBase() { /* ... */ } + virtual Result ProcessRequest() = 0; + }; + + template + concept IsServiceObject = std::derived_from; + +} +