kern: Skeleton KSynchronizationObject

This commit is contained in:
Michael Scire 2020-01-29 23:46:55 -08:00
parent 2faf3d33b5
commit 7d6b16d7fb
6 changed files with 350 additions and 16 deletions

View file

@ -23,24 +23,27 @@ namespace ams::kern {
class KProcess; class KProcess;
#define MESOSPHERE_AUTOOBJECT_TRAITS(CLASS) \ #define MESOSPHERE_AUTOOBJECT_TRAITS(CLASS, BASE_CLASS) \
NON_COPYABLE(CLASS); \
NON_MOVEABLE(CLASS); \
private: \ private: \
friend class KClassTokenGenerator; \ 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 const char * const TypeName = #CLASS; \
static constexpr inline ClassTokenType ClassToken = ClassToken<CLASS>; \ static constexpr inline ClassTokenType ClassToken() { return ::ams::kern::ClassToken<CLASS>; } \
public: \ 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; } \ static constexpr ALWAYS_INLINE const char *GetStaticTypeName() { return TypeName; } \
virtual TypeObj GetTypeObj() const { return TypeObj(TypeName, ClassToken); } \ virtual TypeObj GetTypeObj() const { return GetStaticTypeObj(); } \
virtual const char *GetTypeName() { return TypeName; } \ virtual const char *GetTypeName() { return GetStaticTypeName(); } \
private: private:
class KAutoObject { class KAutoObject {
NON_COPYABLE(KAutoObject);
NON_MOVEABLE(KAutoObject);
protected: protected:
class TypeObj { class TypeObj {
private: private:
@ -64,6 +67,8 @@ namespace ams::kern {
return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken(); return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken();
} }
}; };
private:
MESOSPHERE_AUTOOBJECT_TRAITS(KAutoObject, KAutoObject);
private: private:
std::atomic<u32> ref_count; std::atomic<u32> ref_count;
public: public:
@ -141,9 +146,6 @@ namespace ams::kern {
this->Destroy(); this->Destroy();
} }
} }
/* Ensure that we have functional type object getters. */
MESOSPHERE_AUTOOBJECT_TRAITS(KAutoObject);
}; };
class KAutoObjectWithListContainer; class KAutoObjectWithListContainer;

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <mesosphere/kern_k_typed_address.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
namespace ams::kern {
class KLinkedListNode : public util::IntrusiveListBaseNode<KLinkedListNode>, public KSlabAllocated<KLinkedListNode> {
private:
void *item;
public:
constexpr KLinkedListNode() : util::IntrusiveListBaseNode<KLinkedListNode>(), 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<typename T>
class KLinkedList : private util::IntrusiveListBaseTraits<KLinkedListNode>::ListType {
private:
using BaseList = util::IntrusiveListBaseTraits<KLinkedListNode>::ListType;
public:
template<bool Const>
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<false>;
using const_iterator = Iterator<true>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
template<bool Const>
class Iterator {
private:
using BaseIterator = BaseList::Iterator<Const>;
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<Const, KLinkedList::const_pointer, KLinkedList::pointer>::type;
using reference = typename std::conditional<Const, KLinkedList::const_reference, KLinkedList::reference>::type;
private:
BaseIterator base_it;
public:
explicit Iterator(BaseIterator it) : base_it(it) { /* ... */ }
T *GetItem() const {
static_cast<pointer>(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<true>() const {
return Iterator<true>(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;
}
};
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <mesosphere/kern_k_auto_object.hpp>
#include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_k_linked_list.hpp>
namespace ams::kern {
class KThread;
class KSynchronizationObject : public KAutoObjectWithList {
MESOSPHERE_AUTOOBJECT_TRAITS(KSynchronizationObject, KAutoObject);
public:
using ThreadList = KLinkedList<KThread>;
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();
};
}

View file

@ -15,11 +15,12 @@
*/ */
#pragma once #pragma once
#include <mesosphere/kern_slab_helpers.hpp> #include <mesosphere/kern_slab_helpers.hpp>
#include <mesosphere/kern_k_synchronization_object.hpp>
namespace ams::kern { namespace ams::kern {
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject> {
class KThread : KAutoObjectWithSlabHeapAndContainer<KThread, /* TODO: KSynchronizationObject */ KAutoObjectWithList> { MESOSPHERE_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
public: public:
struct StackParameters { struct StackParameters {
alignas(0x10) u8 svc_permission[0x10]; alignas(0x10) u8 svc_permission[0x10];
@ -32,7 +33,7 @@ namespace ams::kern {
void *context; /* TODO: KThreadContext * */ void *context; /* TODO: KThreadContext * */
}; };
static_assert(alignof(StackParameters) == 0x10); static_assert(alignof(StackParameters) == 0x10);
/* TODO: This should be a KAutoObject, and this is a placeholder definition. */ /* TODO: This is a placeholder definition. */
}; };
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
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();
}
}

View file

@ -183,7 +183,7 @@ namespace ams::util {
} }
}; };
public: public:
IntrusiveListImpl() : root_node() { /* ... */ } constexpr IntrusiveListImpl() : root_node() { /* ... */ }
/* Iterator accessors. */ /* Iterator accessors. */
iterator begin() { iterator begin() {