From 484f1326516d11c91cca6d9745ca52d79a23531e Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 30 Jan 2020 15:29:51 -0800 Subject: [PATCH] kern: implement KHandleTable, other cleanup --- .../libmesosphere/include/mesosphere.hpp | 48 +-- .../arm64/init/kern_k_init_page_table.hpp | 2 +- .../mesosphere/arch/arm64/kern_cpu.hpp | 2 +- .../init/kern_init_arguments_select.hpp | 2 +- .../include/mesosphere/init/kern_init_elf.hpp | 20 +- .../init/kern_init_page_table_select.hpp | 2 +- .../include/mesosphere/kern_common.hpp | 19 ++ .../mesosphere/kern_initial_process.hpp | 3 +- .../include/mesosphere/kern_k_auto_object.hpp | 21 +- .../kern_k_auto_object_container.hpp | 8 +- .../include/mesosphere/kern_k_class_token.hpp | 3 +- .../mesosphere/kern_k_core_local_region.hpp | 2 +- .../mesosphere/kern_k_handle_table.hpp | 283 ++++++++++++++++++ .../include/mesosphere/kern_k_light_lock.hpp | 6 +- .../include/mesosphere/kern_k_linked_list.hpp | 5 +- .../mesosphere/kern_k_memory_layout.hpp | 2 +- .../mesosphere/kern_k_memory_manager.hpp | 2 +- .../include/mesosphere/kern_k_page_heap.hpp | 2 +- .../include/mesosphere/kern_k_slab_heap.hpp | 17 +- .../include/mesosphere/kern_k_spin_lock.hpp | 3 +- .../kern_k_synchronization_object.hpp | 6 +- .../include/mesosphere/kern_k_thread.hpp | 22 ++ .../include/mesosphere/kern_k_timer_task.hpp | 2 +- .../mesosphere/kern_k_typed_address.hpp | 2 +- .../include/mesosphere/kern_main.hpp | 2 +- .../include/mesosphere/kern_panic.hpp | 10 +- .../include/mesosphere/kern_select_cpu.hpp | 2 +- .../mesosphere/kern_select_hardware_timer.hpp | 3 +- .../kern_select_interrupt_controller.hpp | 3 +- .../kern_select_interrupt_manager.hpp | 3 +- .../kern_select_k_system_control.hpp | 2 +- .../include/mesosphere/kern_slab_helpers.hpp | 3 +- .../include/mesosphere/kern_svc.hpp | 7 +- .../svc/kern_svc_k_user_pointer.hpp | 1 + .../mesosphere/svc/kern_svc_prototypes.hpp | 3 +- .../mesosphere/svc/kern_svc_results.hpp | 70 +++++ .../mesosphere/svc/kern_svc_tables.hpp | 1 + .../source/kern_k_auto_object_container.cpp | 6 + .../source/kern_k_handle_table.cpp | 155 ++++++++++ .../source/kern_k_synchronization_object.cpp | 17 ++ .../include/vapours/svc/svc_common.hpp | 27 +- 41 files changed, 710 insertions(+), 89 deletions(-) create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_handle_table.hpp create mode 100644 libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp create mode 100644 libraries/libmesosphere/source/kern_k_handle_table.cpp diff --git a/libraries/libmesosphere/include/mesosphere.hpp b/libraries/libmesosphere/include/mesosphere.hpp index e00f1659b..6f829e2c1 100644 --- a/libraries/libmesosphere/include/mesosphere.hpp +++ b/libraries/libmesosphere/include/mesosphere.hpp @@ -19,40 +19,42 @@ #include /* First, pull in core macros (panic, etc). */ -#include "mesosphere/kern_panic.hpp" +#include +#include /* Primitive types. */ -#include "mesosphere/kern_k_typed_address.hpp" -#include "mesosphere/kern_initial_process.hpp" +#include +#include /* Core pre-initialization includes. */ -#include "mesosphere/kern_select_cpu.hpp" -#include "mesosphere/kern_select_k_system_control.hpp" +#include +#include /* Initialization headers. */ -#include "mesosphere/init/kern_init_elf.hpp" -#include "mesosphere/init/kern_init_layout.hpp" -#include "mesosphere/init/kern_init_slab_setup.hpp" -#include "mesosphere/init/kern_init_page_table_select.hpp" -#include "mesosphere/init/kern_init_arguments_select.hpp" -#include "mesosphere/kern_k_memory_layout.hpp" +#include +#include +#include +#include +#include +#include /* Core functionality. */ -#include "mesosphere/kern_select_interrupt_manager.hpp" -#include "mesosphere/kern_k_spin_lock.hpp" -#include "mesosphere/kern_k_page_heap.hpp" -#include "mesosphere/kern_k_memory_manager.hpp" -#include "mesosphere/kern_k_interrupt_task_manager.hpp" -#include "mesosphere/kern_k_core_local_region.hpp" -#include "mesosphere/kern_k_slab_heap.hpp" -#include "mesosphere/kern_k_light_lock.hpp" -#include "mesosphere/kern_kernel.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Auto Objects. */ -#include "mesosphere/kern_k_auto_object.hpp" +#include +#include /* Supervisor Calls. */ -#include "mesosphere/kern_svc.hpp" +#include /* Main functionality. */ -#include "mesosphere/kern_main.hpp" +#include diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp index e7bc3d758..7d5a0249c 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/init/kern_k_init_page_table.hpp @@ -15,7 +15,7 @@ */ #pragma once #include -#include +#include #include #include diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp index a1cf21ac2..b08bd3b64 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_cpu.hpp @@ -15,7 +15,7 @@ */ #pragma once #include -#include "kern_cpu_system_registers.hpp" +#include namespace ams::kern::arm64::cpu { diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_arguments_select.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_arguments_select.hpp index 9c8858b72..09360267f 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_arguments_select.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_arguments_select.hpp @@ -17,7 +17,7 @@ #include #ifdef ATMOSPHERE_ARCH_ARM64 - #include "../arch/arm64/init/kern_k_init_arguments.hpp" + #include #else #error "Unknown architecture for KInitArguments" #endif diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp index 02aee4a5d..294bee9c6 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_elf.hpp @@ -17,23 +17,21 @@ #include #ifdef ATMOSPHERE_ARCH_ARM64 - #include "kern_init_elf64.hpp" + #include + + namespace ams::kern::init::Elf { + using namespace ams::kern::init::Elf::Elf64; + + enum RelocationType { + R_ARCHITECTURE_RELATIVE = 0x403, /* Real name R_AARCH64_RELATIVE */ + }; + } #else #error "Unknown Architecture" #endif namespace ams::kern::init::Elf { - #ifdef ATMOSPHERE_ARCH_ARM64 - using namespace ams::kern::init::Elf::Elf64; - - enum RelocationType { - R_ARCHITECTURE_RELATIVE = 0x403, /* Real name R_AARCH64_RELATIVE */ - }; - #else - #error "Unknown Architecture" - #endif - /* API to apply relocations or call init array. */ void ApplyRelocations(uintptr_t base_address, const Dyn *dynamic); void CallInitArrayFuncs(uintptr_t init_array_start, uintptr_t init_array_end); diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_page_table_select.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_page_table_select.hpp index d13c8e49c..c68b00d56 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_page_table_select.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_page_table_select.hpp @@ -16,7 +16,7 @@ #pragma once #ifdef ATMOSPHERE_ARCH_ARM64 - #include "../arch/arm64/init/kern_k_init_page_table.hpp" + #include #else #error "Unknown architecture for KInitialPageTable" #endif diff --git a/libraries/libmesosphere/include/mesosphere/kern_common.hpp b/libraries/libmesosphere/include/mesosphere/kern_common.hpp index e69de29bb..7fa55dbdd 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_common.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_common.hpp @@ -0,0 +1,19 @@ +/* + * 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 diff --git a/libraries/libmesosphere/include/mesosphere/kern_initial_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_initial_process.hpp index e4674aa1a..179eee497 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_initial_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_initial_process.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include "kern_panic.hpp" +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp index ea38cc063..04198f0c7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include +#include #include #include @@ -74,14 +73,14 @@ namespace ams::kern { public: static KAutoObject *Create(KAutoObject *ptr); public: - constexpr ALWAYS_INLINE explicit KAutoObject() : ref_count(0) { /* ... */ } - virtual ~KAutoObject() { /* ... */ } + constexpr ALWAYS_INLINE explicit KAutoObject() : ref_count(0) { MESOSPHERE_ASSERT_THIS(); } + virtual ~KAutoObject() { MESOSPHERE_ASSERT_THIS(); } /* Destroy is responsible for destroying the auto object's resources when ref_count hits zero. */ - virtual void Destroy() { /* ... */ } + virtual void Destroy() { MESOSPHERE_ASSERT_THIS(); } /* Finalize is responsible for cleaning up resource, but does not destroy the object. */ - virtual void Finalize() { /* ... */ } + virtual void Finalize() { MESOSPHERE_ASSERT_THIS(); } virtual KProcess *GetOwner() const { return nullptr; } @@ -122,6 +121,8 @@ namespace ams::kern { } ALWAYS_INLINE bool Open() { + MESOSPHERE_ASSERT_THIS(); + /* Atomically increment the reference count, only if it's positive. */ u32 cur_ref_count = this->ref_count.load(std::memory_order_acquire); do { @@ -135,6 +136,8 @@ namespace ams::kern { } ALWAYS_INLINE void Close() { + MESOSPHERE_ASSERT_THIS(); + /* Atomically decrement the reference count, not allowing it to become negative. */ u32 cur_ref_count = this->ref_count.load(std::memory_order_acquire); do { @@ -189,7 +192,11 @@ namespace ams::kern { } public: constexpr ALWAYS_INLINE KScopedAutoObject() : obj(nullptr) { /* ... */ } - constexpr ALWAYS_INLINE KScopedAutoObject(T *o) : obj(o) { /* ... */ } + constexpr ALWAYS_INLINE KScopedAutoObject(T *o) : obj(o) { + if (this->obj != nullptr) { + this->obj->Open(); + } + } ALWAYS_INLINE ~KScopedAutoObject() { if (this->obj != nullptr) { this->obj->Close(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object_container.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object_container.hpp index 52504f667..3d501bdf1 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_auto_object_container.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_auto_object_container.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include #include @@ -51,10 +51,10 @@ namespace ams::kern { KLightLock lock; ListType object_list; public: - constexpr KAutoObjectWithListContainer() : lock(), object_list() { /* ... */ } + constexpr KAutoObjectWithListContainer() : lock(), object_list() { MESOSPHERE_ASSERT_THIS(); } - void Initialize() { /* Nothing to do. */ } - void Finalize() { /* Nothing to do. */ } + void Initialize() { MESOSPHERE_ASSERT_THIS(); } + void Finalize() { MESOSPHERE_ASSERT_THIS(); } Result Register(KAutoObjectWithList *obj); Result Unregister(KAutoObjectWithList *obj); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp index b1640f6a8..fbbfe0abf 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include +#include #include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_core_local_region.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_core_local_region.hpp index 4422df408..1d37dd612 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_core_local_region.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_core_local_region.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include #include #include diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_handle_table.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_handle_table.hpp new file mode 100644 index 000000000..cde564aa3 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_handle_table.hpp @@ -0,0 +1,283 @@ +/* + * 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 +#include + +namespace ams::kern { + + constexpr ALWAYS_INLINE util::BitPack32 GetHandleBitPack(ams::svc::Handle handle) { + return util::BitPack32{handle}; + } + + class KHandleTable { + NON_COPYABLE(KHandleTable); + NON_MOVEABLE(KHandleTable); + public: + static constexpr size_t MaxTableSize = 1024; + private: + using HandleRawValue = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + using HandleEncoded = util::BitPack32::Field<0, BITSIZEOF(ams::svc::Handle), ams::svc::Handle>; + + using HandleIndex = util::BitPack32::Field<0, 15, u16>; + using HandleLinearId = util::BitPack32::Field; + using HandleReserved = util::BitPack32::Field; + + static constexpr u16 MinLinearId = 1; + static constexpr u16 MaxLinearId = util::BitPack32{std::numeric_limits::max()}.Get(); + + static constexpr ALWAYS_INLINE ams::svc::Handle EncodeHandle(u16 index, u16 linear_id) { + util::BitPack32 pack = {0}; + pack.Set(index); + pack.Set(linear_id); + pack.Set(0); + return pack.Get(); + } + + class Entry { + private: + union { + struct { + u16 linear_id; + u16 type; + } info; + Entry *next_free_entry; + } meta; + KAutoObject *object; + public: + constexpr Entry() : meta(), object(nullptr) { /* ... */ } + + constexpr ALWAYS_INLINE void SetFree(Entry *next) { + this->object = nullptr; + this->meta.next_free_entry = next; + } + + constexpr ALWAYS_INLINE void SetUsed(KAutoObject *obj, u16 linear_id, u16 type) { + this->object = obj; + this->meta.info = { linear_id, type }; + } + + constexpr ALWAYS_INLINE KAutoObject *GetObject() const { return this->object; } + constexpr ALWAYS_INLINE Entry *GetNextFreeEntry() const { return this->meta.next_free_entry; } + constexpr ALWAYS_INLINE u16 GetLinearId() const { return this->meta.info.linear_id; } + constexpr ALWAYS_INLINE u16 GetType() const { return this->meta.info.type; } + }; + private: + mutable KSpinLock lock; + Entry *table; + Entry *free_head; + Entry entries[MaxTableSize]; + u16 table_size; + u16 max_count; + u16 next_linear_id; + u16 count; + public: + constexpr KHandleTable() : + lock(), table(nullptr), free_head(nullptr), entries(), table_size(0), max_count(0), next_linear_id(MinLinearId), count(0) + { MESOSPHERE_ASSERT_THIS(); } + + constexpr NOINLINE Result Initialize(s32 size) { + MESOSPHERE_ASSERT_THIS(); + + R_UNLESS(size <= static_cast(MaxTableSize), svc::ResultOutOfMemory()); + + /* Initialize all fields. */ + this->table = this->entries; + this->table_size = (size <= 0) ? MaxTableSize : table_size; + this->next_linear_id = MinLinearId; + this->count = 0; + this->max_count = 0; + + /* Free all entries. */ + for (size_t i = 0; i < static_cast(this->table_size - 1); i++) { + this->entries[i].SetFree(std::addressof(this->entries[i + 1])); + } + this->entries[this->table_size - 1].SetFree(nullptr); + + this->free_head = std::addressof(this->entries[0]); + + return ResultSuccess(); + } + + constexpr ALWAYS_INLINE size_t GetTableSize() const { return this->table_size; } + constexpr ALWAYS_INLINE size_t GetCount() const { return this->count; } + constexpr ALWAYS_INLINE size_t GetMaxCount() const { return this->max_count; } + + NOINLINE Result Finalize(); + NOINLINE bool Remove(ams::svc::Handle handle); + + template + ALWAYS_INLINE KScopedAutoObject GetObject(ams::svc::Handle handle) const { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + if constexpr (std::is_same::value) { + return this->GetObjectImpl(handle); + } else { + return this->GetObjectImpl(handle)->DynamicCast(); + } + } + + template + ALWAYS_INLINE KScopedAutoObject GetObjectForIpc(ams::svc::Handle handle) const { + /* TODO: static_assert(!std::is_base_of::value); */ + + KAutoObject *obj = this->GetObjectImpl(handle); + if (false /* TODO: obj->DynamicCast() != nullptr */) { + return nullptr; + } + if constexpr (std::is_same::value) { + return obj; + } else { + return obj->DynamicCast(); + } + } + + ALWAYS_INLINE KScopedAutoObject GetObjectByIndex(ams::svc::Handle *out_handle, size_t index) const { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + return this->GetObjectByIndexImpl(out_handle, index); + } + + NOINLINE Result Reserve(ams::svc::Handle *out_handle); + NOINLINE void Unreserve(ams::svc::Handle handle); + + template + ALWAYS_INLINE Result Add(ams::svc::Handle *out_handle, T *obj) { + static_assert(std::is_base_of::value); + return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken()); + } + + template + ALWAYS_INLINE void Register(ams::svc::Handle handle, T *obj) { + static_assert(std::is_base_of::value); + return this->Add(handle, obj, obj->GetTypeObj().GetClassToken()); + } + private: + NOINLINE Result Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type); + NOINLINE void Register(ams::svc::Handle handle, KAutoObject *obj, u16 type); + + constexpr ALWAYS_INLINE Entry *AllocateEntry() { + MESOSPHERE_ASSERT_THIS(); + MESOSPHERE_ASSERT(this->count < this->table_size); + + Entry *entry = this->free_head; + this->free_head = entry->GetNextFreeEntry(); + + this->count++; + this->max_count = std::max(this->max_count, this->count); + + return entry; + } + + constexpr ALWAYS_INLINE void FreeEntry(Entry *entry) { + MESOSPHERE_ASSERT_THIS(); + MESOSPHERE_ASSERT(this->count > 0); + + entry->SetFree(this->free_head); + this->free_head = entry; + + this->count--; + } + + constexpr ALWAYS_INLINE u16 AllocateLinearId() { + const u16 id = this->next_linear_id++; + if (this->next_linear_id > MaxLinearId) { + this->next_linear_id = MinLinearId; + } + return id; + } + + constexpr ALWAYS_INLINE size_t GetEntryIndex(Entry *entry) { + const size_t index = entry - this->table; + MESOSPHERE_ASSERT(index < this->table_size); + return index; + } + + constexpr ALWAYS_INLINE Entry *FindEntry(ams::svc::Handle handle) const { + MESOSPHERE_ASSERT_THIS(); + + /* Unpack the handle. */ + const auto handle_pack = GetHandleBitPack(handle); + const auto raw_value = handle_pack.Get(); + const auto index = handle_pack.Get(); + const auto linear_id = handle_pack.Get(); + const auto reserved = handle_pack.Get(); + MESOSPHERE_ASSERT(reserved == 0); + + /* Validate our indexing information. */ + if (raw_value == 0) { + return nullptr; + } + if (linear_id == 0) { + return nullptr; + } + if (index >= this->table_size) { + return nullptr; + } + + /* Get the entry, and ensure our serial id is correct. */ + Entry *entry = std::addressof(this->table[index]); + if (entry->GetObject() == nullptr) { + return nullptr; + } + if (entry->GetLinearId() != linear_id) { + return nullptr; + } + + return entry; + } + + constexpr NOINLINE KAutoObject *GetObjectImpl(ams::svc::Handle handle) const { + MESOSPHERE_ASSERT_THIS(); + + /* Handles must not have reserved bits set. */ + if (GetHandleBitPack(handle).Get() != 0) { + return nullptr; + } + + if (Entry *entry = this->FindEntry(handle); entry != nullptr) { + return entry->GetObject(); + } else { + return nullptr; + } + } + + constexpr NOINLINE KAutoObject *GetObjectByIndexImpl(ams::svc::Handle *out_handle, size_t index) const { + MESOSPHERE_ASSERT_THIS(); + + /* Index must be in bounds. */ + if (index >= this->table_size || this->table == nullptr) { + return nullptr; + } + + /* Ensure entry has an object. */ + Entry *entry = std::addressof(this->table[index]); + if (entry->GetObject() == nullptr) { + return nullptr; + } + + *out_handle = EncodeHandle(index, entry->GetLinearId()); + return entry->GetObject(); + } + }; + +} diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_light_lock.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_light_lock.hpp index eb0cab5e1..d6097fd54 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_light_lock.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_light_lock.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include #include @@ -27,6 +27,8 @@ namespace ams::kern { constexpr KLightLock() : tag(0) { /* ... */ } void Lock() { + MESOSPHERE_ASSERT_THIS(); + const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer()); while (true) { @@ -45,6 +47,8 @@ namespace ams::kern { } void Unlock() { + MESOSPHERE_ASSERT_THIS(); + const uintptr_t cur_thread = reinterpret_cast(GetCurrentThreadPointer()); uintptr_t expected = cur_thread; if (!this->tag.compare_exchange_weak(expected, 0, std::memory_order_release)) { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp index 80a5f463f..1084f2864 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_linked_list.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include #include @@ -24,9 +24,10 @@ namespace ams::kern { private: void *item; public: - constexpr KLinkedListNode() : util::IntrusiveListBaseNode(), item(nullptr) { /* ... */ } + constexpr KLinkedListNode() : util::IntrusiveListBaseNode(), item(nullptr) { MESOSPHERE_ASSERT_THIS(); } constexpr void Initialize(void *it) { + MESOSPHERE_ASSERT_THIS(); this->item = it; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp index c72eee498..aee5f47af 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_layout.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include #include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp index f958d4e34..00f296ec7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp index 2a74efdc3..bc00103d6 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp index e504ef539..2d24df367 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include +#include #include namespace ams::kern { @@ -33,7 +32,7 @@ namespace ams::kern { std::atomic head; size_t obj_size; public: - constexpr KSlabHeapImpl() : head(nullptr), obj_size(0) { /* ... */ } + constexpr KSlabHeapImpl() : head(nullptr), obj_size(0) { MESOSPHERE_ASSERT_THIS(); } void Initialize(size_t size) { MESOSPHERE_INIT_ABORT_UNLESS(this->head == nullptr); @@ -49,6 +48,8 @@ namespace ams::kern { } void *Allocate() { + MESOSPHERE_ASSERT_THIS(); + Node *ret = this->head.load(); do { @@ -61,6 +62,8 @@ namespace ams::kern { } void Free(void *obj) { + MESOSPHERE_ASSERT_THIS(); + Node *node = reinterpret_cast(obj); Node *cur_head = this->head.load(); @@ -90,13 +93,15 @@ namespace ams::kern { return std::addressof(this->impl); } public: - constexpr KSlabHeapBase() : impl(), peak(0), start(0), end(0) { /* ... */ } + constexpr KSlabHeapBase() : impl(), peak(0), start(0), end(0) { MESOSPHERE_ASSERT_THIS(); } ALWAYS_INLINE bool Contains(uintptr_t address) const { return this->start <= address && address < this->end; } void InitializeImpl(size_t obj_size, void *memory, size_t memory_size) { + MESOSPHERE_ASSERT_THIS(); + /* Ensure we don't initialize a slab using null memory. */ MESOSPHERE_ABORT_UNLESS(memory != nullptr); @@ -127,6 +132,8 @@ namespace ams::kern { } void *AllocateImpl() { + MESOSPHERE_ASSERT_THIS(); + void *obj = this->GetImpl()->Allocate(); /* TODO: under some debug define, track the peak for statistics, as N does? */ @@ -135,6 +142,8 @@ namespace ams::kern { } void FreeImpl(void *obj) { + MESOSPHERE_ASSERT_THIS(); + /* Don't allow freeing an object that wasn't allocated from this heap. */ MESOSPHERE_ABORT_UNLESS(this->Contains(reinterpret_cast(obj))); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_spin_lock.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_spin_lock.hpp index 915c94fe9..c1088a3b8 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_spin_lock.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_spin_lock.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include "kern_panic.hpp" +#include #if defined(ATMOSPHERE_ARCH_ARM64) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp index 929aaca66..9f7934cd9 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_synchronization_object.hpp @@ -30,10 +30,10 @@ namespace ams::kern { private: ThreadList thread_list; protected: - constexpr ALWAYS_INLINE explicit KSynchronizationObject() : KAutoObjectWithList(), thread_list() { /* ... */ } - virtual ~KSynchronizationObject() { /* ... */ } + constexpr ALWAYS_INLINE explicit KSynchronizationObject() : KAutoObjectWithList(), thread_list() { MESOSPHERE_ASSERT_THIS(); } + virtual ~KSynchronizationObject() { MESOSPHERE_ASSERT_THIS(); } - virtual void OnFinalizeSynchronizationObject() { /* ... */ } + virtual void OnFinalizeSynchronizationObject() { MESOSPHERE_ASSERT_THIS(); } void NotifyAvailable(); void NotifyAbort(Result abort_reason); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp index c1345698a..a34f4e800 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_thread.hpp @@ -36,4 +36,26 @@ namespace ams::kern { /* TODO: This is a placeholder definition. */ }; + class KScopedDisableDispatch { + public: + explicit ALWAYS_INLINE KScopedDisableDispatch() { + /* TODO */ + } + + ALWAYS_INLINE ~KScopedDisableDispatch() { + /* TODO */ + } + }; + + class KScopedEnableDispatch { + public: + explicit ALWAYS_INLINE KScopedEnableDispatch() { + /* TODO */ + } + + ALWAYS_INLINE ~KScopedEnableDispatch() { + /* TODO */ + } + }; + } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_timer_task.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_timer_task.hpp index d57899ce8..dba2e1c16 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_timer_task.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_timer_task.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_typed_address.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_typed_address.hpp index 97af400ca..3e967624d 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_typed_address.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_typed_address.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_main.hpp b/libraries/libmesosphere/include/mesosphere/kern_main.hpp index d01cbbbfe..f1935bdde 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_main.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_main.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { diff --git a/libraries/libmesosphere/include/mesosphere/kern_panic.hpp b/libraries/libmesosphere/include/mesosphere/kern_panic.hpp index c245b3904..8a41955c6 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_panic.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_panic.hpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include +#include namespace ams::kern { @@ -37,12 +37,18 @@ namespace ams::kern { } \ }) #else -#define MESOSPHERE_ASSERT_IMPL(expr, ...) do { } while (0) +#define MESOSPHERE_ASSERT_IMPL(expr, ...) do { static_cast(expr); } while (0) #endif #define MESOSPHERE_ASSERT(expr) MESOSPHERE_ASSERT_IMPL(expr, "Assertion failed: %s", #expr) #define MESOSPHERE_R_ASSERT(expr) MESOSPHERE_ASSERT_IMPL(R_SUCCEEDED(expr), "Result assertion failed: %s", #expr) +#ifdef MESOSPHERE_ENABLE_THIS_ASSERT +#define MESOSPHERE_ASSERT_THIS() MESOSPHERE_ASSERT(this != nullptr) +#else +#define MESOSPHERE_ASSERT_THIS() +#endif + #define MESOSPHERE_ABORT() MESOSPHERE_PANIC("Abort()"); #define MESOSPHERE_INIT_ABORT() do { /* ... */ } while (true) diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_cpu.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_cpu.hpp index 93bc2434e..6c3ac104b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_cpu.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_cpu.hpp @@ -16,7 +16,7 @@ #pragma once #ifdef ATMOSPHERE_ARCH_ARM64 - #include "arch/arm64/kern_cpu.hpp" + #include namespace ams::kern::cpu { diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_hardware_timer.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_hardware_timer.hpp index db8d6e4f4..bf5fedd70 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_hardware_timer.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_hardware_timer.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include "kern_panic.hpp" +#include #if defined(ATMOSPHERE_ARCH_ARM64) diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_controller.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_controller.hpp index e9bbd2ff6..236c96bb5 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_controller.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_controller.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include "kern_panic.hpp" +#include #if defined(ATMOSPHERE_ARCH_ARM64) diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_manager.hpp index cab08dd0d..9fa9790fa 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_interrupt_manager.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include "kern_panic.hpp" +#include #if defined(ATMOSPHERE_ARCH_ARM64) diff --git a/libraries/libmesosphere/include/mesosphere/kern_select_k_system_control.hpp b/libraries/libmesosphere/include/mesosphere/kern_select_k_system_control.hpp index 066a317cc..ff53a5fe3 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_select_k_system_control.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_select_k_system_control.hpp @@ -16,7 +16,7 @@ #pragma once #ifdef ATMOSPHERE_BOARD_NINTENDO_SWITCH - #include "board/nintendo/switch/kern_k_system_control.hpp" + #include #else #error "Unknown board for KSystemControl" #endif diff --git a/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp b/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp index 31cf1613a..a5155dea5 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp @@ -14,8 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include -#include +#include #include #include #include diff --git a/libraries/libmesosphere/include/mesosphere/kern_svc.hpp b/libraries/libmesosphere/include/mesosphere/kern_svc.hpp index 694b30165..56073530c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_svc.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_svc.hpp @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #pragma once -#include "svc/kern_svc_k_user_pointer.hpp" -#include "svc/kern_svc_prototypes.hpp" -#include "svc/kern_svc_tables.hpp" +#include +#include +#include +#include diff --git a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_k_user_pointer.hpp b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_k_user_pointer.hpp index 7ea3811f4..1c0968b8d 100644 --- a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_k_user_pointer.hpp +++ b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_k_user_pointer.hpp @@ -15,6 +15,7 @@ */ #pragma once #include +#include namespace ams::kern::svc { diff --git a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_prototypes.hpp b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_prototypes.hpp index c66e4f8ed..dd71d5722 100644 --- a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_prototypes.hpp +++ b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_prototypes.hpp @@ -15,7 +15,8 @@ */ #pragma once #include -#include "kern_svc_k_user_pointer.hpp" +#include +#include namespace ams::kern::svc { diff --git a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp new file mode 100644 index 000000000..29eb82690 --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp @@ -0,0 +1,70 @@ +/* + * 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::kern::svc { + + /* 7 */ using ::ams::svc::ResultOutOfSessions; + + /* 14 */ using ::ams::svc::ResultInvalidArgument; + + /* 33 */ using ::ams::svc::ResultNotImplemented; + + /* 59 */ using ::ams::svc::ResultThreadTerminating; + + /* 70 */ using ::ams::svc::ResultNoEvent; + + /* 101 */ using ::ams::svc::ResultInvalidSize; + /* 102 */ using ::ams::svc::ResultInvalidAddress; + /* 103 */ using ::ams::svc::ResultOutOfResource; + /* 104 */ using ::ams::svc::ResultOutOfMemory; + /* 105 */ using ::ams::svc::ResultOutOfHandles; + /* 106 */ using ::ams::svc::ResultInvalidCurrentMemoryState; + + /* 108 */ using ::ams::svc::ResultInvalidNewMemoryPermissions; + + /* 110 */ using ::ams::svc::ResultInvalidMemoryRegion; + + /* 112 */ using ::ams::svc::ResultInvalidPriority; + /* 113 */ using ::ams::svc::ResultInvalidCoreId; + /* 114 */ using ::ams::svc::ResultInvalidHandle; + /* 115 */ using ::ams::svc::ResultInvalidPointer; + /* 116 */ using ::ams::svc::ResultInvalidCombination; + /* 117 */ using ::ams::svc::ResultTimedOut; + /* 118 */ using ::ams::svc::ResultCancelled; + /* 119 */ using ::ams::svc::ResultOutOfRange; + /* 120 */ using ::ams::svc::ResultInvalidEnumValue; + /* 121 */ using ::ams::svc::ResultNotFound; + /* 122 */ using ::ams::svc::ResultBusy; + /* 123 */ using ::ams::svc::ResultSessionClosed; + /* 124 */ using ::ams::svc::ResultNotHandled; + /* 125 */ using ::ams::svc::ResultInvalidState; + /* 126 */ using ::ams::svc::ResultReservedValue; + /* 127 */ using ::ams::svc::ResultNotSupported; + /* 128 */ using ::ams::svc::ResultDebug; + /* 129 */ using ::ams::svc::ResultThreadNotOwned; + + /* 131 */ using ::ams::svc::ResultPortClosed; + /* 132 */ using ::ams::svc::ResultLimitReached; + + /* 258 */ using ::ams::svc::ResultReceiveListBroken; + /* 259 */ using ::ams::svc::ResultOutOfAddressSpace; + /* 260 */ using ::ams::svc::ResultMessageTooLarge; + + /* 520 */ using ::ams::svc::ResultProcessTerminated; + +} diff --git a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_tables.hpp b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_tables.hpp index 0afb1940d..c1ff646e2 100644 --- a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_tables.hpp +++ b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_tables.hpp @@ -15,6 +15,7 @@ */ #pragma once #include +#include namespace ams::kern::svc { diff --git a/libraries/libmesosphere/source/kern_k_auto_object_container.cpp b/libraries/libmesosphere/source/kern_k_auto_object_container.cpp index f6cea8023..aebbc8ec8 100644 --- a/libraries/libmesosphere/source/kern_k_auto_object_container.cpp +++ b/libraries/libmesosphere/source/kern_k_auto_object_container.cpp @@ -19,6 +19,8 @@ namespace ams::kern { Result KAutoObjectWithListContainer::Register(KAutoObjectWithList *obj) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); this->object_list.insert(*obj); @@ -27,6 +29,8 @@ namespace ams::kern { } Result KAutoObjectWithListContainer::Unregister(KAutoObjectWithList *obj) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); this->object_list.erase(this->object_list.iterator_to(*obj)); @@ -35,6 +39,8 @@ namespace ams::kern { } size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess *owner) { + MESOSPHERE_ASSERT_THIS(); + KScopedLightLock lk(this->lock); size_t count = 0; diff --git a/libraries/libmesosphere/source/kern_k_handle_table.cpp b/libraries/libmesosphere/source/kern_k_handle_table.cpp new file mode 100644 index 000000000..ca71003a8 --- /dev/null +++ b/libraries/libmesosphere/source/kern_k_handle_table.cpp @@ -0,0 +1,155 @@ +/* + * 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 { + + Result KHandleTable::Finalize() { + MESOSPHERE_ASSERT_THIS(); + + /* Get the table and clear our record of it. */ + Entry *saved_table = nullptr; + u16 saved_table_size = 0; + { + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + std::swap(this->table, saved_table); + std::swap(this->table_size, saved_table_size); + } + + /* Close and free all entries. */ + for (size_t i = 0; i < saved_table_size; i++) { + Entry *entry = std::addressof(saved_table[i]); + + if (KAutoObject *obj = entry->GetObject(); obj != nullptr) { + obj->Close(); + this->FreeEntry(entry); + } + } + + return ResultSuccess(); + } + + bool KHandleTable::Remove(ams::svc::Handle handle) { + MESOSPHERE_ASSERT_THIS(); + + /* Don't allow removal of a pseudo-handle. */ + if (ams::svc::IsPseudoHandle(handle)) { + return false; + } + + /* Handles must not have reserved bits set. */ + if (GetHandleBitPack(handle).Get() != 0) { + return false; + } + + /* Find the object and free the entry. */ + KAutoObject *obj = nullptr; + { + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + if (Entry *entry = this->FindEntry(handle); entry != nullptr) { + obj = entry->GetObject(); + this->FreeEntry(entry); + } else { + return false; + } + } + + /* Close the object. */ + obj->Close(); + return true; + } + + Result KHandleTable::Add(ams::svc::Handle *out_handle, KAutoObject *obj, u16 type) { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + /* Never exceed our capacity. */ + R_UNLESS(this->count < this->table_size, svc::ResultOutOfHandles()); + + /* Allocate entry, set output handle. */ + { + const auto linear_id = this->AllocateLinearId(); + Entry *entry = this->AllocateEntry(); + entry->SetUsed(obj, linear_id, type); + obj->Open(); + *out_handle = EncodeHandle(this->GetEntryIndex(entry), linear_id); + } + + return ResultSuccess(); + } + + Result KHandleTable::Reserve(ams::svc::Handle *out_handle) { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + /* Never exceed our capacity. */ + R_UNLESS(this->count < this->table_size, svc::ResultOutOfHandles()); + + *out_handle = EncodeHandle(this->GetEntryIndex(this->AllocateEntry()), this->AllocateLinearId()); + return ResultSuccess(); + } + + void KHandleTable::Unreserve(ams::svc::Handle handle) { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + /* Unpack the handle. */ + const auto handle_pack = GetHandleBitPack(handle); + const auto index = handle_pack.Get(); + const auto linear_id = handle_pack.Get(); + const auto reserved = handle_pack.Get(); + MESOSPHERE_ASSERT(reserved == 0); + MESOSPHERE_ASSERT(linear_id != 0); + MESOSPHERE_ASSERT(index < this->table_size); + + /* Free the entry. */ + /* NOTE: This code does not check the linear id. */ + Entry *entry = std::addressof(this->table[index]); + MESOSPHERE_ASSERT(entry->GetObject() == nullptr); + + this->FreeEntry(entry); + } + + void KHandleTable::Register(ams::svc::Handle handle, KAutoObject *obj, u16 type) { + MESOSPHERE_ASSERT_THIS(); + KScopedDisableDispatch dd; + KScopedSpinLock lk(this->lock); + + /* Unpack the handle. */ + const auto handle_pack = GetHandleBitPack(handle); + const auto index = handle_pack.Get(); + const auto linear_id = handle_pack.Get(); + const auto reserved = handle_pack.Get(); + MESOSPHERE_ASSERT(reserved == 0); + MESOSPHERE_ASSERT(linear_id != 0); + MESOSPHERE_ASSERT(index < this->table_size); + + /* Set the entry. */ + Entry *entry = std::addressof(this->table[index]); + MESOSPHERE_ASSERT(entry->GetObject() == nullptr); + + entry->SetUsed(obj, linear_id, type); + obj->Open(); + } + +} diff --git a/libraries/libmesosphere/source/kern_k_synchronization_object.cpp b/libraries/libmesosphere/source/kern_k_synchronization_object.cpp index 942bf2759..54bd488b4 100644 --- a/libraries/libmesosphere/source/kern_k_synchronization_object.cpp +++ b/libraries/libmesosphere/source/kern_k_synchronization_object.cpp @@ -18,36 +18,53 @@ namespace ams::kern { void NotifyAvailable() { + MESOSPHERE_ASSERT_THIS(); + /* TODO: Implement this. */ MESOSPHERE_ABORT(); } void NotifyAbort(Result abort_reason) { + MESOSPHERE_ASSERT_THIS(); + + /* TODO: Implement this. */ MESOSPHERE_ABORT(); } void KSynchronizationObject::Finalize() { + MESOSPHERE_ASSERT_THIS(); + this->OnFinalizeSynchronizationObject(); KAutoObject::Finalize(); } void KSynchronizationObject::DebugWaiters() { + MESOSPHERE_ASSERT_THIS(); + /* TODO: Do useful debug operation here. */ } KSynchronizationObject::iterator KSynchronizationObject::AddWaiterThread(KThread *thread) { + MESOSPHERE_ASSERT_THIS(); + return this->thread_list.insert(this->thread_list.end(), *thread); } KSynchronizationObject::iterator KSynchronizationObject::RemoveWaiterThread(KSynchronizationObject::iterator it) { + MESOSPHERE_ASSERT_THIS(); + return this->thread_list.erase(it); } KSynchronizationObject::iterator KSynchronizationObject::begin() { + MESOSPHERE_ASSERT_THIS(); + return this->thread_list.begin(); } KSynchronizationObject::iterator KSynchronizationObject::end() { + MESOSPHERE_ASSERT_THIS(); + return this->thread_list.end(); } diff --git a/libraries/libvapours/include/vapours/svc/svc_common.hpp b/libraries/libvapours/include/vapours/svc/svc_common.hpp index f60170667..938490191 100644 --- a/libraries/libvapours/include/vapours/svc/svc_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_common.hpp @@ -15,7 +15,7 @@ */ #pragma once -#include "../results.hpp" +#include namespace ams::svc { @@ -28,6 +28,31 @@ namespace ams::svc { #error "Unknown target for svc::Handle" #endif + enum class PseudoHandle : Handle { + CurrentThread = 0xFFFF8000, + CurrentProcess = 0xFFFF8001, + }; + + constexpr ALWAYS_INLINE bool operator==(const Handle &lhs, const PseudoHandle &rhs) { + return static_cast(lhs) == static_cast(rhs); + } + + constexpr ALWAYS_INLINE bool operator==(const PseudoHandle &lhs, const Handle &rhs) { + return static_cast(lhs) == static_cast(rhs); + } + + constexpr ALWAYS_INLINE bool operator!=(const Handle &lhs, const PseudoHandle &rhs) { + return !(lhs == rhs); + } + + constexpr ALWAYS_INLINE bool operator!=(const PseudoHandle &lhs, const Handle &rhs) { + return !(lhs == rhs); + } + + constexpr ALWAYS_INLINE bool IsPseudoHandle(const Handle &handle) { + return handle == PseudoHandle::CurrentProcess || handle == PseudoHandle::CurrentThread; + } + #ifdef ATMOSPHERE_ARCH_ARM64