mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 08:22:04 +00:00
kern: implement unsuspension of init threads
This commit is contained in:
parent
c568788609
commit
aae3c789f2
10 changed files with 117 additions and 17 deletions
|
@ -25,6 +25,11 @@ namespace ams::kern::arch::arm64 {
|
||||||
public:
|
public:
|
||||||
constexpr KProcessPageTable() : page_table() { /* ... */ }
|
constexpr KProcessPageTable() : page_table() { /* ... */ }
|
||||||
|
|
||||||
|
void Activate(u64 id) {
|
||||||
|
/* Activate the page table with the specified contextidr. */
|
||||||
|
this->page_table.Activate(id);
|
||||||
|
}
|
||||||
|
|
||||||
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
Result Initialize(u32 id, ams::svc::CreateProcessFlag as_type, bool enable_aslr, bool from_back, KMemoryManager::Pool pool, KProcessAddress code_address, size_t code_size, KMemoryBlockSlabManager *mem_block_slab_manager, KBlockInfoManager *block_info_manager, KPageTableManager *pt_manager) {
|
||||||
return this->page_table.InitializeForProcess(id, as_type, enable_aslr, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
return this->page_table.InitializeForProcess(id, as_type, enable_aslr, from_back, pool, code_address, code_size, mem_block_slab_manager, block_info_manager, pt_manager);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,19 @@ namespace ams::kern::arch::arm64 {
|
||||||
constexpr KSupervisorPageTable() : page_table(), ttbr0() { /* ... */ }
|
constexpr KSupervisorPageTable() : page_table(), ttbr0() { /* ... */ }
|
||||||
|
|
||||||
NOINLINE void Initialize(s32 core_id);
|
NOINLINE void Initialize(s32 core_id);
|
||||||
NOINLINE void Activate();
|
|
||||||
|
void Activate() {
|
||||||
|
/* Activate, using process id = 0xFFFFFFFF */
|
||||||
|
this->page_table.Activate(0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActivateForInit() {
|
||||||
|
this->Activate();
|
||||||
|
|
||||||
|
/* Invalidate entire TLB. */
|
||||||
|
cpu::InvalidateEntireTlb();
|
||||||
|
}
|
||||||
|
|
||||||
void Finalize(s32 core_id);
|
void Finalize(s32 core_id);
|
||||||
|
|
||||||
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||||
|
|
|
@ -149,6 +149,11 @@ namespace ams::kern {
|
||||||
|
|
||||||
constexpr KResourceLimit *GetResourceLimit() const { return this->resource_limit; }
|
constexpr KResourceLimit *GetResourceLimit() const { return this->resource_limit; }
|
||||||
|
|
||||||
|
bool ReserveResource(ams::svc::LimitableResource which, s64 value);
|
||||||
|
bool ReserveResource(ams::svc::LimitableResource which, s64 value, s64 timeout);
|
||||||
|
void ReleaseResource(ams::svc::LimitableResource which, s64 value);
|
||||||
|
void ReleaseResource(ams::svc::LimitableResource which, s64 value, s64 hint);
|
||||||
|
|
||||||
constexpr KProcessPageTable &GetPageTable() { return this->page_table; }
|
constexpr KProcessPageTable &GetPageTable() { return this->page_table; }
|
||||||
constexpr const KProcessPageTable &GetPageTable() const { return this->page_table; }
|
constexpr const KProcessPageTable &GetPageTable() const { return this->page_table; }
|
||||||
|
|
||||||
|
@ -158,6 +163,9 @@ namespace ams::kern {
|
||||||
Result CreateThreadLocalRegion(KProcessAddress *out);
|
Result CreateThreadLocalRegion(KProcessAddress *out);
|
||||||
void *GetThreadLocalRegionPointer(KProcessAddress addr);
|
void *GetThreadLocalRegionPointer(KProcessAddress addr);
|
||||||
|
|
||||||
|
void AddCpuTime(s64 diff) { this->cpu_time += diff; }
|
||||||
|
void IncrementScheduledCount() { ++this->schedule_count; }
|
||||||
|
|
||||||
void IncrementThreadCount();
|
void IncrementThreadCount();
|
||||||
void DecrementThreadCount();
|
void DecrementThreadCount();
|
||||||
|
|
||||||
|
@ -167,6 +175,18 @@ namespace ams::kern {
|
||||||
Result Run(s32 priority, size_t stack_size);
|
Result Run(s32 priority, size_t stack_size);
|
||||||
|
|
||||||
void SetPreemptionState();
|
void SetPreemptionState();
|
||||||
|
|
||||||
|
static void Switch(KProcess *cur_process, KProcess *next_process) {
|
||||||
|
/* Set the current process pointer. */
|
||||||
|
SetCurrentProcess(next_process);
|
||||||
|
|
||||||
|
/* Update the current page table. */
|
||||||
|
if (next_process) {
|
||||||
|
next_process->GetPageTable().Activate(next_process->GetProcessId());
|
||||||
|
} else {
|
||||||
|
Kernel::GetKernelPageTable().Activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
/* Overridden parent functions. */
|
/* Overridden parent functions. */
|
||||||
virtual bool IsInitialized() const override { return this->is_initialized; }
|
virtual bool IsInitialized() const override { return this->is_initialized; }
|
||||||
|
|
|
@ -201,6 +201,8 @@ namespace ams::kern {
|
||||||
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner) {
|
static Result InitializeUserThread(KThread *thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 core, KProcess *owner) {
|
||||||
return InitializeThread(thread, func, arg, user_stack_top, prio, core, owner, ThreadType_User);
|
return InitializeThread(thread, func, arg, user_stack_top, prio, core, owner, ThreadType_User);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ResumeThreadsSuspendedForInit();
|
||||||
private:
|
private:
|
||||||
StackParameters &GetStackParameters() {
|
StackParameters &GetStackParameters() {
|
||||||
return *(reinterpret_cast<StackParameters *>(this->kernel_stack_top) - 1);
|
return *(reinterpret_cast<StackParameters *>(this->kernel_stack_top) - 1);
|
||||||
|
@ -280,6 +282,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
|
constexpr uintptr_t GetConditionVariableKey() const { return this->condvar_key; }
|
||||||
|
|
||||||
|
constexpr s32 GetIdealCore() const { return this->ideal_core_id; }
|
||||||
constexpr s32 GetActiveCore() const { return this->core_id; }
|
constexpr s32 GetActiveCore() const { return this->core_id; }
|
||||||
constexpr void SetActiveCore(s32 core) { this->core_id = core; }
|
constexpr void SetActiveCore(s32 core) { this->core_id = core; }
|
||||||
constexpr s32 GetPriority() const { return this->priority; }
|
constexpr s32 GetPriority() const { return this->priority; }
|
||||||
|
@ -332,6 +335,7 @@ namespace ams::kern {
|
||||||
constexpr u32 GetSuspendFlags() const { return this->suspend_allowed_flags & this->suspend_request_flags; }
|
constexpr u32 GetSuspendFlags() const { return this->suspend_allowed_flags & this->suspend_request_flags; }
|
||||||
constexpr bool IsSuspended() const { return this->GetSuspendFlags() != 0; }
|
constexpr bool IsSuspended() const { return this->GetSuspendFlags() != 0; }
|
||||||
void RequestSuspend(SuspendType type);
|
void RequestSuspend(SuspendType type);
|
||||||
|
void Resume(SuspendType type);
|
||||||
void TrySuspend();
|
void TrySuspend();
|
||||||
void Continue();
|
void Continue();
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,12 @@ namespace ams::kern {
|
||||||
static ALWAYS_INLINE void Free(Derived *obj) {
|
static ALWAYS_INLINE void Free(Derived *obj) {
|
||||||
s_slab_heap.Free(obj);
|
s_slab_heap.Free(obj);
|
||||||
}
|
}
|
||||||
|
public:
|
||||||
|
class ListAccessor : public KAutoObjectWithListContainer::ListAccessor {
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE ListAccessor() : KAutoObjectWithListContainer::ListAccessor(s_container) { /* ... */ }
|
||||||
|
ALWAYS_INLINE ~ListAccessor() { /* ... */ }
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
constexpr KAutoObjectWithSlabHeapAndContainer() : Base() { /* ... */ }
|
constexpr KAutoObjectWithSlabHeapAndContainer() : Base() { /* ... */ }
|
||||||
virtual ~KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
|
virtual ~KAutoObjectWithSlabHeapAndContainer() { /* ... */ }
|
||||||
|
|
|
@ -39,14 +39,6 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSupervisorPageTable::Activate() {
|
|
||||||
/* Initialize, using process id = 0xFFFFFFFF */
|
|
||||||
this->page_table.Initialize(0xFFFFFFFF);
|
|
||||||
|
|
||||||
/* Invalidate entire TLB. */
|
|
||||||
cpu::InvalidateEntireTlb();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KSupervisorPageTable::Finalize(s32 core_id) {
|
void KSupervisorPageTable::Finalize(s32 core_id) {
|
||||||
MESOSPHERE_TODO_IMPLEMENT();
|
MESOSPHERE_TODO_IMPLEMENT();
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,34 @@ namespace ams::kern {
|
||||||
return static_cast<u8 *>(tlp->GetPointer()) + (GetInteger(addr) & (PageSize - 1));
|
return static_cast<u8 *>(tlp->GetPointer()) + (GetInteger(addr) & (PageSize - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KProcess::ReserveResource(ams::svc::LimitableResource which, s64 value) {
|
||||||
|
if (KResourceLimit *rl = this->GetResourceLimit(); rl != nullptr) {
|
||||||
|
return rl->Reserve(which, value);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KProcess::ReserveResource(ams::svc::LimitableResource which, s64 value, s64 timeout) {
|
||||||
|
if (KResourceLimit *rl = this->GetResourceLimit(); rl != nullptr) {
|
||||||
|
return rl->Reserve(which, value, timeout);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KProcess::ReleaseResource(ams::svc::LimitableResource which, s64 value) {
|
||||||
|
if (KResourceLimit *rl = this->GetResourceLimit(); rl != nullptr) {
|
||||||
|
rl->Release(which, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KProcess::ReleaseResource(ams::svc::LimitableResource which, s64 value, s64 hint) {
|
||||||
|
if (KResourceLimit *rl = this->GetResourceLimit(); rl != nullptr) {
|
||||||
|
rl->Release(which, value, hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KProcess::IncrementThreadCount() {
|
void KProcess::IncrementThreadCount() {
|
||||||
MESOSPHERE_ASSERT(this->num_threads >= 0);
|
MESOSPHERE_ASSERT(this->num_threads >= 0);
|
||||||
++this->num_created_threads;
|
++this->num_created_threads;
|
||||||
|
@ -335,6 +363,9 @@ namespace ams::kern {
|
||||||
stack_guard.Cancel();
|
stack_guard.Cancel();
|
||||||
mem_reservation.Commit();
|
mem_reservation.Commit();
|
||||||
|
|
||||||
|
/* Note for debug that we're running a new process. */
|
||||||
|
MESOSPHERE_LOG("KProcess::Run() pid=%ld name=%-12s thread=%ld affinity=0x%lx ideal_core=%d active_core=%d\n", this->process_id, this->name, main_thread->GetId(), main_thread->GetAffinityMask().GetAffinityMask(), main_thread->GetIdealCore(), main_thread->GetActiveCore());
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
ALWAYS_INLINE void IncrementScheduledCount(KThread *thread) {
|
ALWAYS_INLINE void IncrementScheduledCount(KThread *thread) {
|
||||||
if (KProcess *parent = thread->GetOwnerProcess(); parent != nullptr) {
|
if (KProcess *parent = thread->GetOwnerProcess(); parent != nullptr) {
|
||||||
MESOSPHERE_TODO("parent->IncrementScheduledCount();");
|
parent->IncrementScheduledCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ namespace ams::kern {
|
||||||
const s64 tick_diff = cur_tick - prev_tick;
|
const s64 tick_diff = cur_tick - prev_tick;
|
||||||
cur_thread->AddCpuTime(tick_diff);
|
cur_thread->AddCpuTime(tick_diff);
|
||||||
if (cur_process != nullptr) {
|
if (cur_process != nullptr) {
|
||||||
MESOSPHERE_TODO("cur_process->AddCpuTime(tick_diff);");
|
cur_process->AddCpuTime(tick_diff);
|
||||||
}
|
}
|
||||||
this->last_context_switch_time = cur_tick;
|
this->last_context_switch_time = cur_tick;
|
||||||
|
|
||||||
|
@ -252,7 +252,7 @@ namespace ams::kern {
|
||||||
|
|
||||||
/* Switch the current process, if we're switching processes. */
|
/* Switch the current process, if we're switching processes. */
|
||||||
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
|
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
|
||||||
MESOSPHERE_TODO("KProcess::Switch");
|
KProcess::Switch(cur_process, next_process);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the new thread. */
|
/* Set the new thread. */
|
||||||
|
|
|
@ -232,12 +232,23 @@ namespace ams::kern {
|
||||||
void KThread::PostDestroy(uintptr_t arg) {
|
void KThread::PostDestroy(uintptr_t arg) {
|
||||||
KProcess *owner = reinterpret_cast<KProcess *>(arg & ~1ul);
|
KProcess *owner = reinterpret_cast<KProcess *>(arg & ~1ul);
|
||||||
const bool resource_limit_release_hint = (arg & 1);
|
const bool resource_limit_release_hint = (arg & 1);
|
||||||
|
const s64 hint_value = (resource_limit_release_hint ? 0 : 1);
|
||||||
if (owner != nullptr) {
|
if (owner != nullptr) {
|
||||||
MESOSPHERE_TODO("Release from owner resource limit.");
|
owner->ReleaseResource(ams::svc::LimitableResource_ThreadCountMax, 1, hint_value);
|
||||||
(void)(resource_limit_release_hint);
|
|
||||||
owner->Close();
|
owner->Close();
|
||||||
} else {
|
} else {
|
||||||
MESOSPHERE_TODO("Release from system resource limit.");
|
Kernel::GetSystemResourceLimit().Release(ams::svc::LimitableResource_ThreadCountMax, 1, hint_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KThread::ResumeThreadsSuspendedForInit() {
|
||||||
|
KThread::ListAccessor list_accessor;
|
||||||
|
{
|
||||||
|
KScopedSchedulerLock sl;
|
||||||
|
|
||||||
|
for (auto &thread : list_accessor) {
|
||||||
|
static_cast<KThread &>(thread).Resume(SuspendType_Init);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +321,8 @@ namespace ams::kern {
|
||||||
Result KThread::SetPriorityToIdle() {
|
Result KThread::SetPriorityToIdle() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
|
KScopedSchedulerLock sl;
|
||||||
|
|
||||||
/* Change both our priorities to the idle thread priority. */
|
/* Change both our priorities to the idle thread priority. */
|
||||||
const s32 old_priority = this->priority;
|
const s32 old_priority = this->priority;
|
||||||
this->priority = IdleThreadPriority;
|
this->priority = IdleThreadPriority;
|
||||||
|
@ -325,12 +338,28 @@ namespace ams::kern {
|
||||||
KScopedSchedulerLock lk;
|
KScopedSchedulerLock lk;
|
||||||
|
|
||||||
/* Note the request in our flags. */
|
/* Note the request in our flags. */
|
||||||
this->suspend_request_flags |= (1 << (ThreadState_SuspendShift + type));
|
this->suspend_request_flags |= (1u << (ThreadState_SuspendShift + type));
|
||||||
|
|
||||||
/* Try to perform the suspend. */
|
/* Try to perform the suspend. */
|
||||||
this->TrySuspend();
|
this->TrySuspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KThread::Resume(SuspendType type) {
|
||||||
|
MESOSPHERE_ASSERT_THIS();
|
||||||
|
|
||||||
|
KScopedSchedulerLock sl;
|
||||||
|
|
||||||
|
/* Clear the request in our flags. */
|
||||||
|
this->suspend_request_flags &= ~(1u << (ThreadState_SuspendShift + type));
|
||||||
|
|
||||||
|
/* Update our state. */
|
||||||
|
const ThreadState old_state = this->thread_state;
|
||||||
|
this->thread_state = static_cast<ThreadState>(this->GetSuspendFlags() | (old_state & ThreadState_Mask));
|
||||||
|
if (this->thread_state != old_state) {
|
||||||
|
KScheduler::OnThreadStateChanged(this, old_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KThread::TrySuspend() {
|
void KThread::TrySuspend() {
|
||||||
MESOSPHERE_ASSERT_THIS();
|
MESOSPHERE_ASSERT_THIS();
|
||||||
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
MESOSPHERE_ASSERT(KScheduler::IsSchedulerLockedByCurrentThread());
|
||||||
|
|
|
@ -122,7 +122,8 @@ namespace ams::kern {
|
||||||
/* We're done initializing! */
|
/* We're done initializing! */
|
||||||
Kernel::SetState(Kernel::State::Initialized);
|
Kernel::SetState(Kernel::State::Initialized);
|
||||||
|
|
||||||
MESOSPHERE_TODO("KThread::ResumeThreadsSuspendedForInit();");
|
/* Resume all threads suspended while we initialized. */
|
||||||
|
KThread::ResumeThreadsSuspendedForInit();
|
||||||
}
|
}
|
||||||
cpu::SynchronizeAllCores();
|
cpu::SynchronizeAllCores();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue