mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
kern: add KProcess members
This commit is contained in:
parent
772e1f1c4f
commit
fba8fb539d
15 changed files with 460 additions and 96 deletions
|
@ -20,7 +20,10 @@
|
|||
namespace ams::kern::arch::arm64 {
|
||||
|
||||
class KProcessPageTable {
|
||||
|
||||
private:
|
||||
KPageTable page_table;
|
||||
public:
|
||||
constexpr KProcessPageTable() : page_table() { /* ... */ }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
|
@ -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. */
|
||||
};
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
}
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
24
libraries/libmesosphere/source/kern_k_wait_object.cpp
Normal file
24
libraries/libmesosphere/source/kern_k_wait_object.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue