mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
kern: implement KHandleTable, other cleanup
This commit is contained in:
parent
d5a4c17ee7
commit
484f132651
41 changed files with 710 additions and 89 deletions
|
@ -19,40 +19,42 @@
|
|||
#include <vapours.hpp>
|
||||
|
||||
/* First, pull in core macros (panic, etc). */
|
||||
#include "mesosphere/kern_panic.hpp"
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
/* Primitive types. */
|
||||
#include "mesosphere/kern_k_typed_address.hpp"
|
||||
#include "mesosphere/kern_initial_process.hpp"
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
#include <mesosphere/kern_initial_process.hpp>
|
||||
|
||||
/* Core pre-initialization includes. */
|
||||
#include "mesosphere/kern_select_cpu.hpp"
|
||||
#include "mesosphere/kern_select_k_system_control.hpp"
|
||||
#include <mesosphere/kern_select_cpu.hpp>
|
||||
#include <mesosphere/kern_select_k_system_control.hpp>
|
||||
|
||||
/* 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 <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>
|
||||
|
||||
/* 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 <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>
|
||||
|
||||
/* Auto Objects. */
|
||||
#include "mesosphere/kern_k_auto_object.hpp"
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_k_handle_table.hpp>
|
||||
|
||||
/* Supervisor Calls. */
|
||||
#include "mesosphere/kern_svc.hpp"
|
||||
#include <mesosphere/kern_svc.hpp>
|
||||
|
||||
/* Main functionality. */
|
||||
#include "mesosphere/kern_main.hpp"
|
||||
#include <mesosphere/kern_main.hpp>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
#include <mesosphere/kern_select_cpu.hpp>
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_cpu_system_registers.hpp"
|
||||
#include <mesosphere/arch/arm64/kern_cpu_system_registers.hpp>
|
||||
|
||||
namespace ams::kern::arm64::cpu {
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "../arch/arm64/init/kern_k_init_arguments.hpp"
|
||||
#include <mesosphere/arch/arm64/init/kern_k_init_arguments.hpp>
|
||||
#else
|
||||
#error "Unknown architecture for KInitArguments"
|
||||
#endif
|
||||
|
|
|
@ -17,23 +17,21 @@
|
|||
#include <vapours.hpp>
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "kern_init_elf64.hpp"
|
||||
#include <mesosphere/init/kern_init_elf64.hpp>
|
||||
|
||||
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);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "../arch/arm64/init/kern_k_init_page_table.hpp"
|
||||
#include <mesosphere/arch/arm64/init/kern_k_init_page_table.hpp>
|
||||
#else
|
||||
#error "Unknown architecture for KInitialPageTable"
|
||||
#endif
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
#include <mesosphere/kern_k_class_token.hpp>
|
||||
|
||||
|
@ -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();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_k_light_lock.hpp>
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_select_cpu.hpp>
|
||||
#include <mesosphere/kern_k_current_context.hpp>
|
||||
#include <mesosphere/kern_k_scheduler.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_k_spin_lock.hpp>
|
||||
#include <mesosphere/kern_k_thread.hpp>
|
||||
|
||||
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<HandleIndex::Next, 15, u16>;
|
||||
using HandleReserved = util::BitPack32::Field<HandleLinearId::Next, 2, u32>;
|
||||
|
||||
static constexpr u16 MinLinearId = 1;
|
||||
static constexpr u16 MaxLinearId = util::BitPack32{std::numeric_limits<u32>::max()}.Get<HandleLinearId>();
|
||||
|
||||
static constexpr ALWAYS_INLINE ams::svc::Handle EncodeHandle(u16 index, u16 linear_id) {
|
||||
util::BitPack32 pack = {0};
|
||||
pack.Set<HandleIndex>(index);
|
||||
pack.Set<HandleLinearId>(linear_id);
|
||||
pack.Set<HandleReserved>(0);
|
||||
return pack.Get<HandleEncoded>();
|
||||
}
|
||||
|
||||
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<s32>(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<size_t>(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<typename T = KAutoObject>
|
||||
ALWAYS_INLINE KScopedAutoObject<T> GetObject(ams::svc::Handle handle) const {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
KScopedDisableDispatch dd;
|
||||
KScopedSpinLock lk(this->lock);
|
||||
|
||||
if constexpr (std::is_same<T, KAutoObject>::value) {
|
||||
return this->GetObjectImpl(handle);
|
||||
} else {
|
||||
return this->GetObjectImpl(handle)->DynamicCast<T*>();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T = KAutoObject>
|
||||
ALWAYS_INLINE KScopedAutoObject<T> GetObjectForIpc(ams::svc::Handle handle) const {
|
||||
/* TODO: static_assert(!std::is_base_of<KInterruptEvent, T>::value); */
|
||||
|
||||
KAutoObject *obj = this->GetObjectImpl(handle);
|
||||
if (false /* TODO: obj->DynamicCast<KInterruptEvent *>() != nullptr */) {
|
||||
return nullptr;
|
||||
}
|
||||
if constexpr (std::is_same<T, KAutoObject>::value) {
|
||||
return obj;
|
||||
} else {
|
||||
return obj->DynamicCast<T*>();
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KScopedAutoObject<KAutoObject> 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<typename T>
|
||||
ALWAYS_INLINE Result Add(ams::svc::Handle *out_handle, T *obj) {
|
||||
static_assert(std::is_base_of<KAutoObject, T>::value);
|
||||
return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ALWAYS_INLINE void Register(ams::svc::Handle handle, T *obj) {
|
||||
static_assert(std::is_base_of<KAutoObject, T>::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<HandleRawValue>();
|
||||
const auto index = handle_pack.Get<HandleIndex>();
|
||||
const auto linear_id = handle_pack.Get<HandleLinearId>();
|
||||
const auto reserved = handle_pack.Get<HandleReserved>();
|
||||
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<HandleReserved>() != 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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_select_cpu.hpp>
|
||||
#include <mesosphere/kern_k_current_context.hpp>
|
||||
|
||||
|
@ -27,6 +27,8 @@ namespace ams::kern {
|
|||
constexpr KLightLock() : tag(0) { /* ... */ }
|
||||
|
||||
void Lock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer());
|
||||
|
||||
while (true) {
|
||||
|
@ -45,6 +47,8 @@ namespace ams::kern {
|
|||
}
|
||||
|
||||
void Unlock() {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
|
||||
const uintptr_t cur_thread = reinterpret_cast<uintptr_t>(GetCurrentThreadPointer());
|
||||
uintptr_t expected = cur_thread;
|
||||
if (!this->tag.compare_exchange_weak(expected, 0, std::memory_order_release)) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
#include <mesosphere/kern_slab_helpers.hpp>
|
||||
|
||||
|
@ -24,9 +24,10 @@ namespace ams::kern {
|
|||
private:
|
||||
void *item;
|
||||
public:
|
||||
constexpr KLinkedListNode() : util::IntrusiveListBaseNode<KLinkedListNode>(), item(nullptr) { /* ... */ }
|
||||
constexpr KLinkedListNode() : util::IntrusiveListBaseNode<KLinkedListNode>(), item(nullptr) { MESOSPHERE_ASSERT_THIS(); }
|
||||
|
||||
constexpr void Initialize(void *it) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
this->item = it;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/init/kern_init_page_table_select.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_typed_address.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
@ -33,7 +32,7 @@ namespace ams::kern {
|
|||
std::atomic<Node *> 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<Node *>(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<uintptr_t>(obj)));
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
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<void>(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)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_ARCH_ARM64
|
||||
#include "arch/arm64/kern_cpu.hpp"
|
||||
#include <mesosphere/arch/arm64/kern_cpu.hpp>
|
||||
|
||||
namespace ams::kern::cpu {
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_panic.hpp"
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef ATMOSPHERE_BOARD_NINTENDO_SWITCH
|
||||
#include "board/nintendo/switch/kern_k_system_control.hpp"
|
||||
#include <mesosphere/board/nintendo/switch/kern_k_system_control.hpp>
|
||||
#else
|
||||
#error "Unknown board for KSystemControl"
|
||||
#endif
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/kern_panic.hpp>
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_auto_object.hpp>
|
||||
#include <mesosphere/kern_k_slab_heap.hpp>
|
||||
#include <mesosphere/kern_k_auto_object_container.hpp>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "svc/kern_svc_k_user_pointer.hpp"
|
||||
#include "svc/kern_svc_prototypes.hpp"
|
||||
#include "svc/kern_svc_tables.hpp"
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
||||
#include <mesosphere/svc/kern_svc_k_user_pointer.hpp>
|
||||
#include <mesosphere/svc/kern_svc_prototypes.hpp>
|
||||
#include <mesosphere/svc/kern_svc_tables.hpp>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "kern_svc_k_user_pointer.hpp"
|
||||
#include <mesosphere/svc/kern_svc_k_user_pointer.hpp>
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
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;
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <mesosphere/svc/kern_svc_results.hpp>
|
||||
|
||||
namespace ams::kern::svc {
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
155
libraries/libmesosphere/source/kern_k_handle_table.cpp
Normal file
155
libraries/libmesosphere/source/kern_k_handle_table.cpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mesosphere.hpp>
|
||||
|
||||
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<HandleReserved>() != 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<HandleIndex>();
|
||||
const auto linear_id = handle_pack.Get<HandleLinearId>();
|
||||
const auto reserved = handle_pack.Get<HandleReserved>();
|
||||
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<HandleIndex>();
|
||||
const auto linear_id = handle_pack.Get<HandleLinearId>();
|
||||
const auto reserved = handle_pack.Get<HandleReserved>();
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include "../results.hpp"
|
||||
#include <vapours/results.hpp>
|
||||
|
||||
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<Handle>(lhs) == static_cast<Handle>(rhs);
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool operator==(const PseudoHandle &lhs, const Handle &rhs) {
|
||||
return static_cast<Handle>(lhs) == static_cast<Handle>(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
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue