From 7d6b16d7fb0965e578b6862defc27437abd512ca Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 29 Jan 2020 23:46:55 -0800 Subject: [PATCH] kern: Skeleton KSynchronizationObject --- .../include/mesosphere/kern_k_auto_object.hpp | 26 +- .../include/mesosphere/kern_k_linked_list.hpp | 225 ++++++++++++++++++ .../kern_k_synchronization_object.hpp | 52 ++++ .../include/mesosphere/kern_k_thread.hpp | 7 +- .../source/kern_k_synchronization_object.cpp | 54 +++++ .../vapours/util/util_intrusive_list.hpp | 2 +- 6 files changed, 350 insertions(+), 16 deletions(-) create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp create mode 100644 libraries/libmesosphere/source/kern_k_synchronization_object.cpp diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp index 19bcf949d..ea38cc063 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp @@ -23,24 +23,27 @@ namespace ams::kern { class KProcess; - #define MESOSPHERE_AUTOOBJECT_TRAITS(CLASS) \ + #define MESOSPHERE_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \ + NON_COPYABLE(CLASS); \ + NON_MOVEABLE(CLASS); \ private: \ friend class KClassTokenGenerator; \ - static constexpr inline auto ObjectType = KClassTokenGenerator::ObjectType::CLASS; \ + static constexpr inline auto ObjectType = ::ams::kern::KClassTokenGenerator::ObjectType::CLASS; \ static constexpr inline const char * const TypeName = #CLASS; \ - static constexpr inline ClassTokenType ClassToken = ClassToken; \ + static constexpr inline ClassTokenType ClassToken() { return ::ams::kern::ClassToken; } \ public: \ - static constexpr ALWAYS_INLINE TypeObj GetStaticTypeObj() { return TypeObj(TypeName, ClassToken); } \ + using BaseClass = BASE_CLASS; \ + static constexpr ALWAYS_INLINE TypeObj GetStaticTypeObj() { \ + constexpr ClassTokenType Token = ClassToken(); \ + return TypeObj(TypeName, Token); \ + } \ static constexpr ALWAYS_INLINE const char *GetStaticTypeName() { return TypeName; } \ - virtual TypeObj GetTypeObj() const { return TypeObj(TypeName, ClassToken); } \ - virtual const char *GetTypeName() { return TypeName; } \ + virtual TypeObj GetTypeObj() const { return GetStaticTypeObj(); } \ + virtual const char *GetTypeName() { return GetStaticTypeName(); } \ private: - class KAutoObject { - NON_COPYABLE(KAutoObject); - NON_MOVEABLE(KAutoObject); protected: class TypeObj { private: @@ -64,6 +67,8 @@ namespace ams::kern { return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken(); } }; + private: + MESOSPHERE_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject); private: std::atomic ref_count; public: @@ -141,9 +146,6 @@ namespace ams::kern { this->Destroy(); } } - - /* Ensure that we have functional type object getters. */ - MESOSPHERE_AUTOOBJECT_TRAITS(KAutoObject); }; class KAutoObjectWithListContainer; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp new file mode 100644 index 000000000..80a5f463f --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp @@ -0,0 +1,225 @@ +/* + * 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::kern { + + class KLinkedListNode : public util::IntrusiveListBaseNode, public KSlabAllocated { + private: + void *item; + public: + constexpr KLinkedListNode() : util::IntrusiveListBaseNode(), item(nullptr) { /* ... */ } + + constexpr void Initialize(void *it) { + this->item = it; + } + + constexpr void *GetItem() const { + return this->item; + } + }; + static_assert(sizeof(KLinkedListNode) == sizeof(util::IntrusiveListNode) + sizeof(void *)); + + template + class KLinkedList : private util::IntrusiveListBaseTraits::ListType { + private: + using BaseList = util::IntrusiveListBaseTraits::ListType; + public: + template + class Iterator; + + using value_type = T; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = value_type *; + using const_pointer = const value_type *; + using reference = value_type &; + using const_reference = const value_type &; + using iterator = Iterator; + using const_iterator = Iterator; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + template + class Iterator { + private: + using BaseIterator = BaseList::Iterator; + friend class KLinkedList; + public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = typename KLinkedList::value_type; + using difference_type = typename KLinkedList::difference_type; + using pointer = typename std::conditional::type; + using reference = typename std::conditional::type; + private: + BaseIterator base_it; + public: + explicit Iterator(BaseIterator it) : base_it(it) { /* ... */ } + + T *GetItem() const { + static_cast(this->base_it->GetItem()); + } + + bool operator==(const Iterator &rhs) const { + return this->base_it == rhs.base_it; + } + + bool operator!=(const Iterator &rhs) const { + return !(*this == rhs); + } + + pointer operator->() const { + return this->GetItem(); + } + + reference operator*() const { + return *this->GetItem(); + } + + Iterator &operator++() { + ++this->base_it; + return *this; + } + + Iterator &operator--() { + --this->base_it; + return *this; + } + + Iterator operator++(int) { + const Iterator it{*this}; + ++(*this); + return it; + } + + Iterator operator--(int) { + const Iterator it{*this}; + --(*this); + return it; + } + + operator Iterator() const { + return Iterator(this->base_it); + } + }; + public: + constexpr KLinkedList() : BaseList() { /* ... */ } + + /* Iterator accessors. */ + iterator begin() { + return iterator(BaseList::begin()); + } + + const_iterator begin() const { + return const_iterator(BaseList::begin()); + } + + iterator end() { + return iterator(BaseList::end()); + } + + const_iterator end() const { + return const_iterator(BaseList::end()); + } + + const_iterator cbegin() const { + return this->begin(); + } + + const_iterator cend() const { + return this->end(); + } + + reverse_iterator rbegin() { + return reverse_iterator(this->end()); + } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(this->end()); + } + + reverse_iterator rend() { + return reverse_iterator(this->begin()); + } + + const_reverse_iterator rend() const { + return const_reverse_iterator(this->begin()); + } + + const_reverse_iterator crbegin() const { + return this->rbegin(); + } + + const_reverse_iterator crend() const { + return this->rend(); + } + + /* Content management. */ + using BaseList::empty; + using BaseList::size; + + reference back() { + return *(--this->end()); + } + + const_reference back() const { + return *(--this->end()); + } + + reference front() { + return *this->begin(); + } + + const_reference front() const { + return *this->begin(); + } + + iterator insert(const_iterator pos, reference ref) { + KLinkedListNode *node = KLinkedListNode::Allocate(); + MESOSPHERE_ABORT_UNLESS(node != nullptr); + node->Initialize(std::addressof(ref)); + return iterator(BaseList::insert(pos.base_it, *node)); + } + + void push_back(reference ref) { + this->insert(this->end(), ref); + } + + void push_front(reference ref) { + this->insert(this->begin(), ref); + } + + void pop_back() { + this->erase(--this->end()); + } + + void pop_front() { + this->erase(this->begin()); + } + + iterator erase(const iterator pos) { + KLinkedListNode *freed_node = std::addressof(*pos.base_it); + iterator ret = iterator(BaseList::erase(pos.base_it)); + KLinkedListNode::Free(freed_node); + + return ret; + } + }; + +} diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp new file mode 100644 index 000000000..929aaca66 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp @@ -0,0 +1,52 @@ +/* + * 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::kern { + + class KThread; + + class KSynchronizationObject : public KAutoObjectWithList { + MESOSPHERE_AUTOOBJECT_TRAITS(KSynchronizationObject, KAutoObject); + public: + using ThreadList = KLinkedList; + using iterator = ThreadList::iterator; + private: + ThreadList thread_list; + protected: + constexpr ALWAYS_INLINE explicit KSynchronizationObject() : KAutoObjectWithList(), thread_list() { /* ... */ } + virtual ~KSynchronizationObject() { /* ... */ } + + virtual void OnFinalizeSynchronizationObject() { /* ... */ } + + void NotifyAvailable(); + void NotifyAbort(Result abort_reason); + public: + virtual void Finalize() override; + virtual bool IsSignaled() const = 0; + virtual void DebugWaiters(); + + iterator AddWaiterThread(KThread *thread); + iterator RemoveWaiterThread(iterator it); + + iterator begin(); + iterator end(); + }; + +} diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index b6f35639a..c1345698a 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -15,11 +15,12 @@ */ #pragma once #include +#include namespace ams::kern { - - class KThread : KAutoObjectWithSlabHeapAndContainer { + class KThread final : public KAutoObjectWithSlabHeapAndContainer { + MESOSPHERE_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); public: struct StackParameters { alignas(0x10) u8 svc_permission[0x10]; @@ -32,7 +33,7 @@ namespace ams::kern { void *context; /* TODO: KThreadContext * */ }; static_assert(alignof(StackParameters) == 0x10); - /* TODO: This should be a KAutoObject, and this is a placeholder definition. */ + /* TODO: This is a placeholder definition. */ }; } diff --git a/libraries/libmesosphere/source/kern_k_synchronization_object.cpp b/libraries/libmesosphere/source/kern_k_synchronization_object.cpp new file mode 100644 index 000000000..942bf2759 --- /dev/null +++ b/libraries/libmesosphere/source/kern_k_synchronization_object.cpp @@ -0,0 +1,54 @@ +/* + * 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 . + */ +#include + +namespace ams::kern { + + void NotifyAvailable() { + /* TODO: Implement this. */ + MESOSPHERE_ABORT(); + } + + void NotifyAbort(Result abort_reason) { + MESOSPHERE_ABORT(); + } + + void KSynchronizationObject::Finalize() { + this->OnFinalizeSynchronizationObject(); + KAutoObject::Finalize(); + } + + void KSynchronizationObject::DebugWaiters() { + /* TODO: Do useful debug operation here. */ + } + + KSynchronizationObject::iterator KSynchronizationObject::AddWaiterThread(KThread *thread) { + return this->thread_list.insert(this->thread_list.end(), *thread); + } + + KSynchronizationObject::iterator KSynchronizationObject::RemoveWaiterThread(KSynchronizationObject::iterator it) { + return this->thread_list.erase(it); + } + + KSynchronizationObject::iterator KSynchronizationObject::begin() { + return this->thread_list.begin(); + } + + KSynchronizationObject::iterator KSynchronizationObject::end() { + return this->thread_list.end(); + } + +} diff --git a/libraries/libvapours/include/vapours/util/util_intrusive_list.hpp b/libraries/libvapours/include/vapours/util/util_intrusive_list.hpp index 0c1cf1468..3a88f6f03 100644 --- a/libraries/libvapours/include/vapours/util/util_intrusive_list.hpp +++ b/libraries/libvapours/include/vapours/util/util_intrusive_list.hpp @@ -183,7 +183,7 @@ namespace ams::util { } }; public: - IntrusiveListImpl() : root_node() { /* ... */ } + constexpr IntrusiveListImpl() : root_node() { /* ... */ } /* Iterator accessors. */ iterator begin() {