mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-02-22 17:21:40 +00:00
kern: KLinkedList no longer exists
This commit is contained in:
parent
b3bd443636
commit
962cf97150
6 changed files with 5 additions and 270 deletions
|
@ -36,7 +36,7 @@ namespace ams::kern {
|
||||||
void Signal(uintptr_t cv_key, s32 count);
|
void Signal(uintptr_t cv_key, s32 count);
|
||||||
Result Wait(KProcessAddress addr, uintptr_t key, u32 value, s64 timeout);
|
Result Wait(KProcessAddress addr, uintptr_t key, u32 value, s64 timeout);
|
||||||
private:
|
private:
|
||||||
KThread *SignalImpl(KThread *thread);
|
void SignalImpl(KThread *thread);
|
||||||
};
|
};
|
||||||
|
|
||||||
ALWAYS_INLINE void BeforeUpdatePriority(KConditionVariable::ThreadTree *tree, KThread *thread) {
|
ALWAYS_INLINE void BeforeUpdatePriority(KConditionVariable::ThreadTree *tree, KThread *thread) {
|
||||||
|
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
* 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_common.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 *m_item;
|
|
||||||
public:
|
|
||||||
constexpr KLinkedListNode() : util::IntrusiveListBaseNode<KLinkedListNode>(), m_item(nullptr) { MESOSPHERE_ASSERT_THIS(); }
|
|
||||||
|
|
||||||
constexpr void Initialize(void *it) {
|
|
||||||
MESOSPHERE_ASSERT_THIS();
|
|
||||||
m_item = it;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr void *GetItem() const {
|
|
||||||
return m_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 m_base_it;
|
|
||||||
public:
|
|
||||||
explicit Iterator(BaseIterator it) : m_base_it(it) { /* ... */ }
|
|
||||||
|
|
||||||
pointer GetItem() const {
|
|
||||||
return static_cast<pointer>(m_base_it->GetItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Iterator &rhs) const {
|
|
||||||
return m_base_it == rhs.m_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++() {
|
|
||||||
++m_base_it;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator &operator--() {
|
|
||||||
--m_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>(m_base_it);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public:
|
|
||||||
constexpr KLinkedList() : BaseList() { /* ... */ }
|
|
||||||
|
|
||||||
~KLinkedList() {
|
|
||||||
/* Erase all elements. */
|
|
||||||
for (auto it = this->begin(); it != this->end(); it = this->erase(it)) {
|
|
||||||
/* ... */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure we succeeded. */
|
|
||||||
MESOSPHERE_ASSERT(this->empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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.m_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.m_base_it);
|
|
||||||
iterator ret = iterator(BaseList::erase(pos.m_base_it));
|
|
||||||
KLinkedListNode::Free(freed_node);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,7 +16,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <mesosphere/kern_k_auto_object.hpp>
|
#include <mesosphere/kern_k_auto_object.hpp>
|
||||||
#include <mesosphere/kern_slab_helpers.hpp>
|
#include <mesosphere/kern_slab_helpers.hpp>
|
||||||
#include <mesosphere/kern_k_linked_list.hpp>
|
|
||||||
|
|
||||||
namespace ams::kern {
|
namespace ams::kern {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ namespace ams::kern::init {
|
||||||
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
||||||
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
||||||
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
|
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
|
||||||
HANDLER(KLinkedListNode, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \
|
|
||||||
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
|
HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
|
@ -77,7 +76,7 @@ namespace ams::kern::init {
|
||||||
|
|
||||||
namespace test {
|
namespace test {
|
||||||
|
|
||||||
constexpr size_t RequiredSizeForExtraThreadCount = SlabCountExtraKThread * (sizeof(KThread) + sizeof(KLinkedListNode) + (sizeof(KThreadLocalPage) / 8) + sizeof(KEventInfo));
|
constexpr size_t RequiredSizeForExtraThreadCount = SlabCountExtraKThread * (sizeof(KThread) + (sizeof(KThreadLocalPage) / 8) + sizeof(KEventInfo));
|
||||||
static_assert(RequiredSizeForExtraThreadCount <= KernelSlabHeapAdditionalSize);
|
static_assert(RequiredSizeForExtraThreadCount <= KernelSlabHeapAdditionalSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ namespace ams::kern {
|
||||||
return cur_thread->GetWaitResult(std::addressof(dummy));
|
return cur_thread->GetWaitResult(std::addressof(dummy));
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread *KConditionVariable::SignalImpl(KThread *thread) {
|
void KConditionVariable::SignalImpl(KThread *thread) {
|
||||||
/* Check pre-conditions. */
|
/* Check pre-conditions. */
|
||||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||||
|
|
||||||
|
@ -137,7 +137,6 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread *thread_to_close = nullptr;
|
|
||||||
if (AMS_LIKELY(can_access)) {
|
if (AMS_LIKELY(can_access)) {
|
||||||
if (prev_tag == ams::svc::InvalidHandle) {
|
if (prev_tag == ams::svc::InvalidHandle) {
|
||||||
/* If nobody held the lock previously, we're all good. */
|
/* If nobody held the lock previously, we're all good. */
|
||||||
|
@ -150,7 +149,7 @@ namespace ams::kern {
|
||||||
if (AMS_LIKELY(owner_thread != nullptr)) {
|
if (AMS_LIKELY(owner_thread != nullptr)) {
|
||||||
/* Add the thread as a waiter on the owner. */
|
/* Add the thread as a waiter on the owner. */
|
||||||
owner_thread->AddWaiter(thread);
|
owner_thread->AddWaiter(thread);
|
||||||
thread_to_close = owner_thread;
|
owner_thread->Close();
|
||||||
} else {
|
} else {
|
||||||
/* The lock was tagged with a thread that doesn't exist. */
|
/* The lock was tagged with a thread that doesn't exist. */
|
||||||
thread->SetSyncedObject(nullptr, svc::ResultInvalidState());
|
thread->SetSyncedObject(nullptr, svc::ResultInvalidState());
|
||||||
|
@ -162,17 +161,9 @@ namespace ams::kern {
|
||||||
thread->SetSyncedObject(nullptr, svc::ResultInvalidCurrentMemory());
|
thread->SetSyncedObject(nullptr, svc::ResultInvalidCurrentMemory());
|
||||||
thread->Wakeup();
|
thread->Wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
return thread_to_close;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KConditionVariable::Signal(uintptr_t cv_key, s32 count) {
|
void KConditionVariable::Signal(uintptr_t cv_key, s32 count) {
|
||||||
/* Prepare for signaling. */
|
|
||||||
constexpr int MaxThreads = 16;
|
|
||||||
KLinkedList<KThread> thread_list;
|
|
||||||
KThread *thread_array[MaxThreads];
|
|
||||||
int num_to_close = 0;
|
|
||||||
|
|
||||||
/* Perform signaling. */
|
/* Perform signaling. */
|
||||||
int num_waiters = 0;
|
int num_waiters = 0;
|
||||||
{
|
{
|
||||||
|
@ -182,14 +173,7 @@ namespace ams::kern {
|
||||||
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
while ((it != m_tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
|
||||||
KThread *target_thread = std::addressof(*it);
|
KThread *target_thread = std::addressof(*it);
|
||||||
|
|
||||||
if (KThread *thread = this->SignalImpl(target_thread); thread != nullptr) {
|
this->SignalImpl(target_thread);
|
||||||
if (num_to_close < MaxThreads) {
|
|
||||||
thread_array[num_to_close++] = thread;
|
|
||||||
} else {
|
|
||||||
thread_list.push_back(*thread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it = m_tree.erase(it);
|
it = m_tree.erase(it);
|
||||||
target_thread->ClearConditionVariable();
|
target_thread->ClearConditionVariable();
|
||||||
++num_waiters;
|
++num_waiters;
|
||||||
|
@ -201,16 +185,6 @@ namespace ams::kern {
|
||||||
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
WriteToUser(cv_key, std::addressof(has_waiter_flag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close threads in the array. */
|
|
||||||
for (auto i = 0; i < num_to_close; ++i) {
|
|
||||||
thread_array[i]->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close threads in the list. */
|
|
||||||
for (auto it = thread_list.begin(); it != thread_list.end(); it = thread_list.erase(it)) {
|
|
||||||
(*it).Close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result KConditionVariable::Wait(KProcessAddress addr, uintptr_t key, u32 value, s64 timeout) {
|
Result KConditionVariable::Wait(KProcessAddress addr, uintptr_t key, u32 value, s64 timeout) {
|
||||||
|
|
|
@ -345,7 +345,6 @@ namespace ams::kern::KDumpObject {
|
||||||
DUMP_KSLABOBJ(KDebug);
|
DUMP_KSLABOBJ(KDebug);
|
||||||
DUMP_KSLABOBJ(KSession);
|
DUMP_KSLABOBJ(KSession);
|
||||||
DUMP_KSLABOBJ(KLightSession);
|
DUMP_KSLABOBJ(KLightSession);
|
||||||
DUMP_KSLABOBJ(KLinkedListNode);
|
|
||||||
DUMP_KSLABOBJ(KThreadLocalPage);
|
DUMP_KSLABOBJ(KThreadLocalPage);
|
||||||
DUMP_KSLABOBJ(KObjectName);
|
DUMP_KSLABOBJ(KObjectName);
|
||||||
DUMP_KSLABOBJ(KEventInfo);
|
DUMP_KSLABOBJ(KEventInfo);
|
||||||
|
|
Loading…
Add table
Reference in a new issue