mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-28 05:06:08 +00:00
kern: Skeleton KSynchronizationObject
This commit is contained in:
parent
2faf3d33b5
commit
7d6b16d7fb
6 changed files with 350 additions and 16 deletions
|
@ -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<CLASS>; \
|
||||
static constexpr inline ClassTokenType ClassToken() { return ::ams::kern::ClassToken<CLASS>; } \
|
||||
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<u32> 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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -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();
|
||||
};
|
||||
|
||||
}
|
|
@ -15,11 +15,12 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
#include <mesosphere/kern_k_synchronization_object.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
||||
class KThread : KAutoObjectWithSlabHeapAndContainer<KThread, /* TODO: KSynchronizationObject */ KAutoObjectWithList> {
|
||||
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject> {
|
||||
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. */
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -183,7 +183,7 @@ namespace ams::util {
|
|||
}
|
||||
};
|
||||
public:
|
||||
IntrusiveListImpl() : root_node() { /* ... */ }
|
||||
constexpr IntrusiveListImpl() : root_node() { /* ... */ }
|
||||
|
||||
/* Iterator accessors. */
|
||||
iterator begin() {
|
||||
|
|
Loading…
Reference in a new issue