kern: add KProcess members

This commit is contained in:
Michael Scire 2020-02-18 05:04:49 -08:00
parent 772e1f1c4f
commit fba8fb539d
15 changed files with 460 additions and 96 deletions

View file

@ -20,7 +20,10 @@
namespace ams::kern::arch::arm64 {
class KProcessPageTable {
private:
KPageTable page_table;
public:
constexpr KProcessPageTable() : page_table() { /* ... */ }
};
}

View file

@ -0,0 +1,61 @@
/*
* 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_condition_variable.hpp>
namespace ams::kern {
class KAddressArbiter {
public:
using ThreadTree = KConditionVariable::ThreadTree;
private:
ThreadTree tree;
public:
constexpr KAddressArbiter() : tree() { /* ... */ }
Result SignalToAddress(uintptr_t addr, ams::svc::SignalType type, s32 value, s32 count) {
switch (type) {
case ams::svc::SignalType_Signal:
return this->Signal(addr, count);
case ams::svc::SignalType_SignalAndIncrementIfEqual:
return this->SignalAndIncrementIfEqual(addr, value, count);
case ams::svc::SignalType_SignalAndModifyByWaitingCountIfEqual:
return this->SignalAndModifyByWaitingCountIfEqual(addr, value, count);
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
}
Result WaitForAddress(uintptr_t addr, ams::svc::ArbitrationType type, s32 value, s64 timeout) {
switch (type) {
case ams::svc::ArbitrationType_WaitIfLessThan:
return this->WaitIfLessThan(addr, value, false, timeout);
case ams::svc::ArbitrationType_DecrementAndWaitIfLessThan:
return this->WaitIfLessThan(addr, value, true, timeout);
case ams::svc::ArbitrationType_WaitIfEqual:
return this->WaitIfEqual(addr, value, timeout);
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
}
}
private:
Result Signal(uintptr_t addr, s32 count);
Result SignalAndIncrementIfEqual(uintptr_t addr, s32 value, s32 count);
Result SignalAndModifyByWaitingCountIfEqual(uintptr_t addr, s32 value, s32 count);
Result WaitIfLessThan(uintptr_t addr, s32 value, bool decrement, s64 timeout);
Result WaitIfEqual(uintptr_t addr, s32 value, s64 timeout);
};
}

View file

@ -0,0 +1,45 @@
/*
* 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_select_page_table.hpp>
#include <mesosphere/kern_svc.hpp>
namespace ams::kern {
class KCapabilities {
private:
static constexpr size_t SvcFlagCount = svc::NumSupervisorCalls / BITSIZEOF(u8);
static constexpr size_t IrqFlagCount = /* TODO */0x80;
private:
u8 svc_access_flags[SvcFlagCount]{};
u8 irq_access_flags[IrqFlagCount]{};
u64 core_mask{};
u64 priority_mask{};
util::BitPack32 debug_capabilities;
s32 handle_table_size{};
util::BitPack32 intended_kernel_version;
u32 program_type{};
public:
constexpr KCapabilities() : svc_access_flags(), debug_capabilities(0), intended_kernel_version(0) { /* ... */ }
constexpr u64 GetCoreMask() const { return this->core_mask; }
constexpr u64 GetPriorityMask() const { return this->priority_mask; }
/* TODO: Member functions. */
};
}

View file

@ -0,0 +1,69 @@
/*
* 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_thread.hpp>
#include <mesosphere/kern_k_scheduler.hpp>
namespace ams::kern {
struct KConditionVariableComparator {
static constexpr ALWAYS_INLINE int Compare(const KThread &lhs, const KThread &rhs) {
const uintptr_t l_key = lhs.GetConditionVariableKey();
const uintptr_t r_key = rhs.GetConditionVariableKey();
if (l_key < r_key) {
/* Sort first by key */
return -1;
} else if (l_key == r_key && lhs.GetPriority() < rhs.GetPriority()) {
/* And then by priority. */
return -1;
} else {
return 1;
}
}
};
class KConditionVariable {
public:
using ThreadTree = util::IntrusiveRedBlackTreeMemberTraits<&KThread::condvar_arbiter_tree_node>::TreeType<KConditionVariableComparator>;
private:
ThreadTree tree;
public:
constexpr KConditionVariable() : tree() { /* ... */ }
/* Arbitration. */
Result SignalToAddress(KProcessAddress addr);
Result WaitForAddress(ams::svc::Handle handle, KProcessAddress addr, u32 value);
/* Condition variable. */
void Signal(uintptr_t cv_key, s32 count);
Result Wait(KProcessAddress addr, uintptr_t key, u32 value, s64 timeout);
ALWAYS_INLINE void BeforeUpdatePriority(KThread *thread) {
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
this->tree.erase(this->tree.iterator_to(*thread));
}
ALWAYS_INLINE void AfterUpdatePriority(KThread *thread) {
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
this->tree.insert(*thread);
}
};
}

View file

@ -21,21 +21,134 @@
#include <mesosphere/kern_k_handle_table.hpp>
#include <mesosphere/kern_k_thread.hpp>
#include <mesosphere/kern_k_thread_local_page.hpp>
#include <mesosphere/kern_k_shared_memory_info.hpp>
#include <mesosphere/kern_k_worker_task.hpp>
#include <mesosphere/kern_select_page_table.hpp>
#include <mesosphere/kern_k_condition_variable.hpp>
#include <mesosphere/kern_k_address_arbiter.hpp>
#include <mesosphere/kern_k_capabilities.hpp>
#include <mesosphere/kern_k_wait_object.hpp>
#include <mesosphere/kern_k_dynamic_slab_heap.hpp>
#include <mesosphere/kern_k_page_table_manager.hpp>
namespace ams::kern {
class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> {
class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>, public KWorkerTask {
MESOSPHERE_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject);
/* TODO: This is a placeholder definition. */
public:
u64 GetCoreMask() const { MESOSPHERE_TODO_IMPLEMENT(); }
u64 GetPriorityMask() const { MESOSPHERE_TODO_IMPLEMENT();}
enum State {
State_Created = ams::svc::ProcessState_Created,
State_CreatedAttached = ams::svc::ProcessState_CreatedAttached,
State_Running = ams::svc::ProcessState_Running,
State_Crashed = ams::svc::ProcessState_Crashed,
State_RunningAttached = ams::svc::ProcessState_RunningAttached,
State_Terminating = ams::svc::ProcessState_Terminating,
State_Terminated = ams::svc::ProcessState_Terminated,
State_DebugBreak = ams::svc::ProcessState_DebugBreak,
};
bool Is64Bit() const { MESOSPHERE_TODO_IMPLEMENT(); }
using ThreadList = util::IntrusiveListMemberTraits<&KThread::process_list_node>::ListType;
private:
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
using TLPIterator = TLPTree::iterator;
private:
KProcessPageTable page_table{};
std::atomic<size_t> used_kernel_memory_size{};
TLPTree fully_used_tlp_tree{};
TLPTree partially_used_tlp_tree{};
s32 ideal_core_id{};
void *attached_object{};
KResourceLimit *resource_limit{};
KVirtualAddress system_resource_address{};
size_t system_resource_num_pages{};
size_t memory_release_hint{};
State state{};
KLightLock lock{};
KLightLock list_lock{};
KConditionVariable cond_var{};
KAddressArbiter address_arbiter{};
u64 entropy[4]{};
bool is_signaled{};
bool is_initialized{};
bool is_application{};
char name[13]{};
std::atomic<u16> num_threads{};
u16 peak_num_threads{};
u32 flags{};
KMemoryManager::Pool memory_pool{};
s64 schedule_count{};
KCapabilities capabilities{};
ams::svc::ProgramId program_id{};
u64 process_id{};
s64 creation_time{};
KProcessAddress code_address{};
size_t code_size{};
size_t main_thread_stack_size{};
size_t max_process_memory{};
u32 version{};
KHandleTable handle_table{};
KProcessAddress plr_address{};
KThread *exception_thread{};
ThreadList thread_list{};
SharedMemoryInfoList shared_memory_list{};
bool is_suspended{};
bool is_jit_debug{};
ams::svc::DebugEvent jit_debug_event_type{};
ams::svc::DebugException jit_debug_exception_type{};
uintptr_t jit_debug_params[4]{};
u64 jit_debug_thread_id{};
KWaitObject wait_object{};
KThread *running_threads[cpu::NumCores]{};
u64 running_thread_idle_counts[cpu::NumCores]{};
KThread *pinned_threads[cpu::NumCores]{};
std::atomic<s32> num_created_threads{};
std::atomic<s64> cpu_time{};
std::atomic<s64> num_process_switches{};
std::atomic<s64> num_thread_switches{};
std::atomic<s64> num_fpu_switches{};
std::atomic<s64> num_supervisor_calls{};
std::atomic<s64> num_ipc_messages{};
std::atomic<s64> num_ipc_replies{};
std::atomic<s64> num_ipc_receives{};
KDynamicPageManager dynamic_page_manager{};
KMemoryBlockSlabManager memory_block_slab_manager{};
KBlockInfoManager block_info_manager{};
KPageTableManager page_table_manager{};
public:
constexpr KProcess() { /* ... */ }
virtual ~KProcess() { /* ... */ }
KThread *GetPreemptionStatePinnedThread(s32 core_id) { MESOSPHERE_TODO_IMPLEMENT(); }
constexpr u64 GetProcessId() const { return this->process_id; }
constexpr u64 GetCoreMask() const { return this->capabilities.GetCoreMask(); }
constexpr u64 GetPriorityMask() const { return this->capabilities.GetPriorityMask(); }
constexpr bool Is64Bit() const { return this->flags & ams::svc::CreateProcessFlag_Is64Bit; }
KThread *GetPreemptionStatePinnedThread(s32 core_id) const {
MESOSPHERE_ASSERT(0 <= core_id && core_id < static_cast<s32>(cpu::NumCores));
return this->pinned_threads[core_id];
}
void SetPreemptionState();
public:
/* Overridden parent functions. */
virtual bool IsInitialized() const override { return this->is_initialized; }
static void PostDestroy(uintptr_t arg) { /* ... */ }
virtual void Finalize() override;
virtual u64 GetId() const override { return this->GetProcessId(); }
virtual bool IsSignaled() const override {
MESOSPHERE_ASSERT_THIS();
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
return this->is_signaled;
}
virtual void DoWorkerTask() override;
};
}

View file

@ -25,11 +25,18 @@
namespace ams::kern {
class KThreadQueue;
class KProcess;
class KConditionVariable;
class KAddressArbiter;
using KThreadFunction = void (*)(uintptr_t);
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, public KTimerTask, public KWorkerTask {
MESOSPHERE_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
private:
friend class KProcess;
friend class KConditionVariable;
friend class KAddressArbiter;
public:
static constexpr s32 MainThreadPriority = 1;
static constexpr s32 IdleThreadPriority = 64;
@ -115,79 +122,66 @@ namespace ams::kern {
private:
static inline std::atomic<u64> s_next_thread_id = 0;
private:
alignas(16) KThreadContext thread_context;
KAffinityMask affinity_mask;
u64 thread_id;
std::atomic<s64> cpu_time;
KSynchronizationObject *synced_object;
KLightLock *waiting_lock;
uintptr_t condvar_key;
uintptr_t entrypoint;
KProcessAddress arbiter_key;
KProcess *parent;
void *kernel_stack_top;
u32 *light_ipc_data;
KProcessAddress tls_address;
void *tls_heap_address;
KLightLock activity_pause_lock;
SyncObjectBuffer sync_object_buffer;
s64 schedule_count;
s64 last_scheduled_tick;
QueueEntry per_core_priority_queue_entry[cpu::NumCores];
QueueEntry sleeping_queue_entry;
KThreadQueue *sleeping_queue;
util::IntrusiveListNode waiter_list_node;
util::IntrusiveRedBlackTreeNode condvar_arbiter_tree_node;
util::IntrusiveListNode process_list_node;
alignas(16) KThreadContext thread_context{};
KAffinityMask affinity_mask{};
u64 thread_id{};
std::atomic<s64> cpu_time{};
KSynchronizationObject *synced_object{};
KLightLock *waiting_lock{};
uintptr_t condvar_key{};
uintptr_t entrypoint{};
KProcessAddress arbiter_key{};
KProcess *parent{};
void *kernel_stack_top{};
u32 *light_ipc_data{};
KProcessAddress tls_address{};
void *tls_heap_address{};
KLightLock activity_pause_lock{};
SyncObjectBuffer sync_object_buffer{};
s64 schedule_count{};
s64 last_scheduled_tick{};
QueueEntry per_core_priority_queue_entry[cpu::NumCores]{};
QueueEntry sleeping_queue_entry{};
KThreadQueue *sleeping_queue{};
util::IntrusiveListNode waiter_list_node{};
util::IntrusiveRedBlackTreeNode condvar_arbiter_tree_node{};
util::IntrusiveListNode process_list_node{};
using WaiterListTraits = util::IntrusiveListMemberTraitsDeferredAssert<&KThread::waiter_list_node>;
using WaiterList = WaiterListTraits::ListType;
WaiterList waiter_list;
WaiterList paused_waiter_list;
KThread *lock_owner;
void /* TODO KCondVar*/ *cond_var_tree;
uintptr_t debug_params[3];
u32 arbiter_value;
u32 suspend_request_flags;
u32 suspend_allowed_flags;
WaiterList waiter_list{};
WaiterList paused_waiter_list{};
KThread *lock_owner{};
KConditionVariable *cond_var{};
uintptr_t debug_params[3]{};
u32 arbiter_value{};
u32 suspend_request_flags{};
u32 suspend_allowed_flags{};
Result wait_result;
Result debug_exception_result;
s32 priority;
s32 core_id;
s32 base_priority;
s32 ideal_core_id;
s32 num_kernel_waiters;
KAffinityMask original_affinity_mask;
s32 original_ideal_core_id;
s32 num_core_migration_disables;
ThreadState thread_state;
std::atomic<bool> termination_requested;
bool ipc_cancelled;
bool wait_cancelled;
bool cancellable;
bool registered;
bool signaled;
bool initialized;
bool debug_attached;
s8 priority_inheritance_count;
bool resource_limit_release_hint;
s32 priority{};
s32 core_id{};
s32 base_priority{};
s32 ideal_core_id{};
s32 num_kernel_waiters{};
KAffinityMask original_affinity_mask{};
s32 original_ideal_core_id{};
s32 num_core_migration_disables{};
ThreadState thread_state{};
std::atomic<bool> termination_requested{};
bool ipc_cancelled{};
bool wait_cancelled{};
bool cancellable{};
bool registered{};
bool signaled{};
bool initialized{};
bool debug_attached{};
s8 priority_inheritance_count{};
bool resource_limit_release_hint{};
public:
constexpr KThread() :
thread_context(), affinity_mask(), thread_id(), cpu_time(), synced_object(), waiting_lock(),
condvar_key(), entrypoint(), arbiter_key(), parent(), kernel_stack_top(), light_ipc_data(),
tls_address(), tls_heap_address(), activity_pause_lock(), sync_object_buffer(), schedule_count(),
last_scheduled_tick(), per_core_priority_queue_entry(), sleeping_queue_entry(), sleeping_queue(), waiter_list_node(),
condvar_arbiter_tree_node(), process_list_node(), waiter_list(), paused_waiter_list(), lock_owner(),
cond_var_tree(), debug_params(), arbiter_value(), suspend_request_flags(), suspend_allowed_flags(),
wait_result(ResultSuccess()), debug_exception_result(ResultSuccess()), priority(), core_id(), base_priority(),
ideal_core_id(), num_kernel_waiters(), original_affinity_mask(), original_ideal_core_id(), num_core_migration_disables(),
thread_state(), termination_requested(), ipc_cancelled(), wait_cancelled(), cancellable(),
registered(), signaled(), initialized(), debug_attached(), priority_inheritance_count(),
resource_limit_release_hint()
{
/* ... */
}
constexpr KThread() : wait_result(svc::ResultNoSynchronizationObject()), debug_exception_result(ResultSuccess()) { /* ... */ }
virtual ~KThread() { /* ... */ }
/* TODO: Is a constexpr KThread() possible? */
@ -271,7 +265,7 @@ namespace ams::kern {
ALWAYS_INLINE void RemoveWaiterImpl(KThread *thread);
ALWAYS_INLINE static void RestorePriority(KThread *thread);
public:
constexpr u64 GetId() const { return this->thread_id; }
constexpr u64 GetThreadId() const { return this->thread_id; }
constexpr KThreadContext *GetContext() { return std::addressof(this->thread_context); }
constexpr const KThreadContext *GetContext() const { return std::addressof(this->thread_context); }
@ -282,6 +276,8 @@ namespace ams::kern {
NOINLINE KThreadContext *GetContextForSchedulerLoop();
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
constexpr s32 GetActiveCore() const { return this->core_id; }
constexpr void SetActiveCore(s32 core) { this->core_id = core; }
constexpr s32 GetPriority() const { return this->priority; }
@ -295,7 +291,7 @@ namespace ams::kern {
constexpr const QueueEntry &GetSleepingQueueEntry() const { return this->sleeping_queue_entry; }
constexpr void SetSleepingQueue(KThreadQueue *q) { this->sleeping_queue = q; }
constexpr void /* TODO */ *GetConditionVariable() const { return this->cond_var_tree; }
constexpr KConditionVariable *GetConditionVariable() const { return this->cond_var; }
constexpr s32 GetNumKernelWaiters() const { return this->num_kernel_waiters; }
@ -354,6 +350,8 @@ namespace ams::kern {
public:
/* Overridden parent functions. */
virtual u64 GetId() const override { return this->GetThreadId(); }
virtual bool IsInitialized() const override { return this->initialized; }
virtual uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast<uintptr_t>(this->parent) | (this->resource_limit_release_hint ? 1 : 0); }

View file

@ -0,0 +1,37 @@
/*
* 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_timer_task.hpp>
#include <mesosphere/kern_k_thread.hpp>
namespace ams::kern {
class KWaitObject : public KTimerTask {
private:
using Entry = KThread::QueueEntry;
private:
Entry root;
bool uses_timer;
public:
constexpr KWaitObject() : root(), uses_timer() { /* ... */ }
virtual void OnTimer() override;
/* TODO: Member functions */
};
}

View file

@ -81,7 +81,8 @@ namespace ams::kern {
MESOSPHERE_R_ABORT_UNLESS(Kernel::GetKernelPageTable().UnmapPageGroup(temp_address, pg, KMemoryState_Kernel));
/* Create a KProcess object. */
MESOSPHERE_TODO("Create a KProcess");
new_process = KProcess::Create();
MESOSPHERE_ABORT_UNLESS(new_process != nullptr);
/* Initialize the process. */
MESOSPHERE_TODO("Initialize the process");

View file

@ -17,6 +17,14 @@
namespace ams::kern {
void KProcess::Finalize() {
MESOSPHERE_TODO_IMPLEMENT();
}
void KProcess::DoWorkerTask() {
MESOSPHERE_TODO_IMPLEMENT();
}
void KProcess::SetPreemptionState() {
MESOSPHERE_TODO_IMPLEMENT();
}

View file

@ -96,7 +96,7 @@ namespace ams::kern {
/* Set parent and condvar tree. */
this->parent = nullptr;
this->cond_var_tree = nullptr;
this->cond_var = nullptr;
/* Set sync booleans. */
this->signaled = false;
@ -423,7 +423,7 @@ namespace ams::kern {
/* Ensure we don't violate condition variable red black tree invariants. */
if (auto *cond_var = thread->GetConditionVariable(); cond_var != nullptr) {
MESOSPHERE_TODO("Remove from condvar tree");
cond_var->BeforeUpdatePriority(thread);
}
/* Change the priority. */
@ -432,7 +432,7 @@ namespace ams::kern {
/* Restore the condition variable, if relevant. */
if (auto *cond_var = thread->GetConditionVariable(); cond_var != nullptr) {
MESOSPHERE_TODO("Re-insert into condvar tree");
cond_var->AfterUpdatePriority(thread);
}
/* Update the scheduler. */

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <mesosphere.hpp>
namespace ams::kern {
void KWaitObject::OnTimer() {
MESOSPHERE_TODO_IMPLEMENT();
}
}

View file

@ -34,9 +34,9 @@ namespace ams::ncm {
/* Program IDs (Formerly: Title IDs). */
struct ProgramId {
u64 value;
svc::ProgramId value;
inline explicit operator u64() const {
inline explicit operator svc::ProgramId() const {
return this->value;
}

View file

@ -64,6 +64,7 @@ namespace ams::svc {
template<typename T>
static constexpr inline bool IsUserPointer = std::is_base_of<impl::UserPointerTag, T>::value;
using ProgramId = u64;
using PhysicalAddress = u64;
/* Memory types. */
@ -197,8 +198,8 @@ namespace ams::svc {
/* Synchronization types. */
enum SignalType : u32 {
SignalType_Signal = 0,
SignalType_SignalAndIfEqual = 1,
SignalType_SignalAndModifyBasedOnWaitingThreadCountIfEqual = 2,
SignalType_SignalAndIncrementIfEqual = 1,
SignalType_SignalAndModifyByWaitingCountIfEqual = 2,
};
enum ArbitrationType : u32 {
@ -291,9 +292,9 @@ namespace ams::svc {
ProcessState_Running = 2,
ProcessState_Crashed = 3,
ProcessState_RunningAttached = 4,
ProcessState_Exiting = 5,
ProcessState_Exited = 6,
ProcessState_DebugSuspended = 7,
ProcessState_Terminating = 5,
ProcessState_Terminated = 6,
ProcessState_DebugBreak = 7,
};
enum ProcessExitReason : u32 {

View file

@ -89,10 +89,10 @@ _ZN3ams4kern4arch5arm6427SupervisorModeThreadStarterEv:
/* ams::kern::arch::arm64::KThreadContext::RestoreFpuRegisters64(const KThreadContext &) */
.section .text._ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS2_, "ax", %progbits
.global _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS2_
.type _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS2_, %function
_ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS2_:
.section .text._ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS3_, "ax", %progbits
.global _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS3_
.type _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS3_, %function
_ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS3_:
/* Load and restore FPCR and FPSR from the context. */
ldr x1, [x0, #0x70]
msr fpcr, x1
@ -120,10 +120,10 @@ _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters64ERKS2_:
ret
/* ams::kern::arch::arm64::KThreadContext::RestoreFpuRegisters32(const KThreadContext &) */
.section .text._ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS2_, "ax", %progbits
.global _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS2_
.type _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS2_, %function
_ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS2_:
.section .text._ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS3_, "ax", %progbits
.global _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS3_
.type _ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS3_, %function
_ZN3ams4kern4arch5arm6414KThreadContext21RestoreFpuRegisters32ERKS3_:
/* Load and restore FPCR and FPSR from the context. */
ldr x1, [x0, #0x70]
msr fpcr, x1

View file

@ -23,6 +23,10 @@ void operator delete (void *deleted, size_t size) throw() {
MESOSPHERE_PANIC("operator delete(void *, size_t) was called: %p %zu", deleted, size);
}
void abort() {
void operator delete (void *deleted, size_t size, std::align_val_t align) throw() {
MESOSPHERE_PANIC("operator delete(void *, size_t, std::align_val_t) was called: %p %zu, %zu", deleted, size, static_cast<size_t>(align));
}
extern "C" void abort() {
MESOSPHERE_PANIC("abort() was called");
}