diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-06-23 06:31:25 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-06-23 06:31:25 +0200 |
| commit | 3aa0d462598beb2021308eee1d757d74fe33b312 (patch) | |
| tree | ed425c3845ba8fa61184d97b0588cb049b518bd7 /src/core/hle/kernel/k_process.cpp | |
| parent | f8facda35fe7f17143f84bbfbdacc4cc48678946 (diff) | |
[video_core, hle] remove redundant parent references in system structs (#3908)
reworked a bit to remove references of parent objects and instead pass as arguments to methods to prevent useless reloads
Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: maufeat <sahyno1996@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3908
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
Diffstat (limited to 'src/core/hle/kernel/k_process.cpp')
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 370 |
1 files changed, 179 insertions, 191 deletions
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index f737a18736..7308b0ff87 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -28,8 +28,7 @@ namespace Kernel { namespace { -Result TerminateChildren(KernelCore& kernel, KProcess* process, - const KThread* thread_to_not_terminate) { +Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* thread_to_not_terminate) { // Request that all children threads terminate. { KScopedLightLock proc_lk(process->GetListLock()); @@ -41,14 +40,14 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // This is valid because the only caller which uses non-nullptr as argument uses // GetCurrentThreadPointer(), but it's still notable because it seems incorrect at // first glance. - process->UnpinCurrentThread(); + process->UnpinCurrentThread(kernel); } auto& thread_list = process->GetThreadList(); for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - thread->RequestTerminate(); + thread->RequestTerminate(kernel); } } } @@ -65,7 +64,7 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, for (auto it = thread_list.begin(); it != thread_list.end(); ++it) { if (KThread* thread = std::addressof(*it); thread != thread_to_not_terminate) { if (thread->GetState() != ThreadState::Terminated) { - if (thread->Open()) { + if (thread->Open(kernel)) { cur_child = thread; break; } @@ -81,11 +80,10 @@ Result TerminateChildren(KernelCore& kernel, KProcess* process, // Terminate and close the thread. SCOPE_EXIT { - cur_child->Close(); + cur_child->Close(kernel); }; - if (const Result terminate_result = cur_child->Terminate(); - ResultTerminationRequested == terminate_result) { + if (const Result terminate_result = cur_child->Terminate(kernel); ResultTerminationRequested == terminate_result) { R_THROW(terminate_result); } } @@ -101,21 +99,21 @@ public: explicit ThreadQueueImplForKProcessEnterUserException(KernelCore& kernel, KThread** t) : KThreadQueue(kernel), m_exception_thread(t) {} - virtual void EndWait(KThread* waiting_thread, Result wait_result) override { + virtual void EndWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result) override { // Set the exception thread. *m_exception_thread = waiting_thread; // Invoke the base end wait handler. - KThreadQueue::EndWait(waiting_thread, wait_result); + KThreadQueue::EndWait(kernel, waiting_thread, wait_result); } - virtual void CancelWait(KThread* waiting_thread, Result wait_result, + virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task) override { // Remove the thread as a waiter on its mutex owner. - waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); + waiting_thread->GetLockOwner(kernel)->RemoveWaiter(kernel, waiting_thread); // Invoke the base cancel wait handler. - KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); + KThreadQueue::CancelWait(kernel, waiting_thread, wait_result, cancel_timer_task); } }; @@ -128,12 +126,12 @@ void GenerateRandom(std::span<u64> out_random) { } // namespace -void KProcess::Finalize() { +void KProcess::Finalize(KernelCore& kernel) { // Delete the process local region. - this->DeleteThreadLocalRegion(m_plr_address); + this->DeleteThreadLocalRegion(kernel, m_plr_address); // Get the used memory size. - const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(); + const size_t used_memory_size = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); // Finalize the page table. m_page_table.Finalize(); @@ -142,10 +140,10 @@ void KProcess::Finalize() { if (m_system_resource) { if (m_system_resource->IsSecureResource()) { // Finalize optimized memory. If memory wasn't optimized, this is a no-op. - m_kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); + kernel.MemoryManager().FinalizeOptimizedMemory(this->GetId(), m_memory_pool); } - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; } @@ -157,12 +155,12 @@ void KProcess::Finalize() { KSharedMemory* shmem = info->GetSharedMemory(); while (!info->Close()) { - shmem->Close(); + shmem->Close(kernel); } - shmem->Close(); + shmem->Close(kernel); it = m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } } @@ -173,9 +171,8 @@ void KProcess::Finalize() { // Release memory to the resource limit. if (m_resource_limit != nullptr) { ASSERT(used_memory_size >= m_memory_release_hint); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, - used_memory_size - m_memory_release_hint); - m_resource_limit->Close(); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, used_memory_size, used_memory_size - m_memory_release_hint); + m_resource_limit->Close(kernel); } // Clear expensive resources, as the destructor is not called for guest objects. @@ -185,15 +182,14 @@ void KProcess::Finalize() { m_exclusive_monitor.reset(); // Perform inherited finalization. - KSynchronizationObject::Finalize(); + KSynchronizationObject::Finalize(kernel); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, - bool is_real) { +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, KResourceLimit* res_limit, bool is_real) { // TODO: remove this special case if (is_real) { // Create and clear the process local region. - R_TRY(this->CreateThreadLocalRegion(std::addressof(m_plr_address))); + R_TRY(this->CreateThreadLocalRegion(kernel, std::addressof(m_plr_address))); this->GetMemory().ZeroBlock(m_plr_address, Svc::ThreadLocalRegionSize); } @@ -259,7 +255,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource // Open a reference to our resource limit. m_resource_limit = res_limit; - m_resource_limit->Open(); + m_resource_limit->Open(kernel); // We're initialized! m_is_initialized = true; @@ -267,7 +263,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, KResource R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPageGroup& pg, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, const KPageGroup& pg, std::span<const u32> caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, bool immortal) { ASSERT(res_limit != nullptr); @@ -283,34 +279,33 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_num_pages * PageSize, res_limit, - m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_num_pages * PageSize, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -330,7 +325,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, @@ -350,18 +345,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(InitialProcessIdMin <= m_process_id); ASSERT(m_process_id <= InitialProcessIdMax); // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded! R_SUCCEED(); } -Result KProcess::Initialize(const Svc::CreateProcessParameter& params, +Result KProcess::Initialize(KernelCore& kernel, const Svc::CreateProcessParameter& params, std::span<const u32> user_caps, KResourceLimit* res_limit, KMemoryManager::Pool pool, KProcessAddress aslr_space_start) { ASSERT(res_limit != nullptr); @@ -378,22 +373,22 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const size_t system_resource_size = system_resource_num_pages * PageSize; // Reserve memory for our code resource. - KScopedResourceReservation memory_reservation( + KScopedResourceReservation memory_reservation(kernel, res_limit, Svc::LimitableResource::PhysicalMemoryMax, code_size); R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); // Setup our system resource. if (system_resource_num_pages != 0) { // Create a secure system resource. - KSecureSystemResource* secure_resource = KSecureSystemResource::Create(m_kernel); + KSecureSystemResource* secure_resource = KSecureSystemResource::Create(kernel); R_UNLESS(secure_resource != nullptr, ResultOutOfResource); ON_RESULT_FAILURE { - secure_resource->Close(); + secure_resource->Close(kernel); }; // Initialize the secure resource. - R_TRY(secure_resource->Initialize(system_resource_size, res_limit, m_memory_pool)); + R_TRY(secure_resource->Initialize(kernel, system_resource_size, res_limit, m_memory_pool)); // Set our system resource. m_system_resource = secure_resource; @@ -401,18 +396,18 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } else { // Use the system-wide system resource. const bool is_app = True(params.flags & Svc::CreateProcessFlag::IsApplication); - m_system_resource = std::addressof(is_app ? m_kernel.GetAppSystemResource() - : m_kernel.GetSystemSystemResource()); + m_system_resource = std::addressof(is_app ? kernel.GetAppSystemResource() + : kernel.GetSystemSystemResource()); m_is_default_application_system_resource = is_app; // Open reference to the system resource. - m_system_resource->Open(); + m_system_resource->Open(kernel); } // Ensure we clean up our secure resource, if we fail. ON_RESULT_FAILURE { - m_system_resource->Close(); + m_system_resource->Close(kernel); m_system_resource = nullptr; }; @@ -432,7 +427,7 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, // Ensure our memory is initialized. m_memory.SetCurrentPageTable(*this); - m_memory.SetGPUDirtyManagers(m_kernel.System().GetGPUDirtyMemoryManager()); + m_memory.SetGPUDirtyManagers(kernel.System().GetGPUDirtyMemoryManager()); // Ensure we can insert the code region. R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), @@ -451,101 +446,99 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, } // Initialize the process id. - m_process_id = m_kernel.CreateNewUserProcessID(); + m_process_id = kernel.CreateNewUserProcessID(); ASSERT(ProcessIdMin <= m_process_id); ASSERT(m_process_id <= ProcessIdMax); // If we should optimize memory allocations, do so. if (m_system_resource->IsSecureResource() && True(params.flags & Svc::CreateProcessFlag::OptimizeMemoryAllocation)) { - R_TRY(m_kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); + R_TRY(kernel.MemoryManager().InitializeOptimizedMemory(m_process_id, pool)); } // Initialize the rest of the process. - R_TRY(this->Initialize(params, res_limit, true)); + R_TRY(this->Initialize(kernel, params, res_limit, true)); // We succeeded, so commit our memory reservation. memory_reservation.Commit(); R_SUCCEED(); } -void KProcess::DoWorkerTaskImpl() { +void KProcess::DoWorkerTaskImpl(KernelCore& kernel) { // Terminate child threads. - TerminateChildren(m_kernel, this, nullptr); + TerminateChildren(kernel, this, nullptr); // Finalize the handle table, if we're not immortal. if (!m_is_immortal && m_is_handle_table_initialized) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } -Result KProcess::StartTermination() { +Result KProcess::StartTermination(KernelCore& kernel) { // Finalize the handle table when we're done, if the process isn't immortal. SCOPE_EXIT { if (!m_is_immortal) { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); } }; // Terminate child threads other than the current one. - R_RETURN(TerminateChildren(m_kernel, this, GetCurrentThreadPointer(m_kernel))); + R_RETURN(TerminateChildren(kernel, this, GetCurrentThreadPointer(kernel))); } -void KProcess::FinishTermination() { +void KProcess::FinishTermination(KernelCore& kernel) { // Only allow termination to occur if the process isn't immortal. if (!m_is_immortal) { // Release resource limit hint. if (m_resource_limit != nullptr) { - m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(); - m_resource_limit->Release(Svc::LimitableResource::PhysicalMemoryMax, 0, - m_memory_release_hint); + m_memory_release_hint = this->GetUsedNonSystemUserPhysicalMemorySize(kernel); + m_resource_limit->Release(kernel, Svc::LimitableResource::PhysicalMemoryMax, 0, m_memory_release_hint); } // Change state. { - KScopedSchedulerLock sl(m_kernel); - this->ChangeState(State::Terminated); + KScopedSchedulerLock sl(kernel); + this->ChangeState(kernel, State::Terminated); } // Close. - this->Close(); + this->Close(kernel); } } -void KProcess::Exit() { +void KProcess::Exit(KernelCore& kernel) { // Determine whether we need to start terminating bool needs_terminate = false; { KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); ASSERT(m_state != State::Created); ASSERT(m_state != State::CreatedAttached); ASSERT(m_state != State::Crashed); ASSERT(m_state != State::Terminated); - if (m_state == State::Running || m_state == State::RunningAttached || - m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::DebugBreak) { + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } // If we need to start termination, do so. if (needs_terminate) { - this->StartTermination(); + this->StartTermination(kernel); // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } // Exit the current thread. - GetCurrentThread(m_kernel).Exit(); + GetCurrentThread(kernel).Exit(kernel); } -Result KProcess::Terminate() { +Result KProcess::Terminate(KernelCore& kernel) { // Determine whether we need to start terminating. bool needs_terminate = false; { @@ -555,11 +548,11 @@ Result KProcess::Terminate() { R_UNLESS(m_state != State::Created, ResultInvalidState); R_UNLESS(m_state != State::CreatedAttached, ResultInvalidState); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (m_state == State::Running || m_state == State::RunningAttached || m_state == State::Crashed || m_state == State::DebugBreak) { - this->ChangeState(State::Terminating); + this->ChangeState(kernel, State::Terminating); needs_terminate = true; } } @@ -567,20 +560,19 @@ Result KProcess::Terminate() { // If we need to terminate, do so. if (needs_terminate) { // Start termination. - if (R_SUCCEEDED(this->StartTermination())) { + if (R_SUCCEEDED(this->StartTermination(kernel))) { // Finish termination. - this->FinishTermination(); + this->FinishTermination(kernel); } else { // Register the process as a work task. - m_kernel.WorkerTaskManager().AddTask(m_kernel, KWorkerTaskManager::WorkerType::Exit, - this); + kernel.WorkerTaskManager().AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); } } R_SUCCEED(); } -Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +Result KProcess::AddSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -596,7 +588,7 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, // If we didn't find an info, create one. if (info == nullptr) { // Allocate a new info. - info = KSharedMemoryInfo::Allocate(m_kernel); + info = KSharedMemoryInfo::Allocate(kernel); R_UNLESS(info != nullptr, ResultOutOfResource); // Initialize the info and add it to our list. @@ -605,13 +597,13 @@ Result KProcess::AddSharedMemory(KSharedMemory* shmem, KProcessAddress address, } // Open a reference to the shared memory and its info. - shmem->Open(); + shmem->Open(kernel); info->Open(); R_SUCCEED(); } -void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, size_t size) { +void KProcess::RemoveSharedMemory(KernelCore& kernel, KSharedMemory* shmem, KProcessAddress address, size_t size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -629,19 +621,19 @@ void KProcess::RemoveSharedMemory(KSharedMemory* shmem, KProcessAddress address, // Close a reference to the info and its memory. if (info->Close()) { m_shared_memory_list.erase(it); - KSharedMemoryInfo::Free(m_kernel, info); + KSharedMemoryInfo::Free(kernel, info); } - shmem->Close(); + shmem->Close(kernel); } -Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { +Result KProcess::CreateThreadLocalRegion(KernelCore& kernel, KProcessAddress* out) { KThreadLocalPage* tlp = nullptr; KProcessAddress tlr = 0; // See if we can get a region from a partially used TLP. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (auto it = m_partially_used_tlp_tree.begin(); it != m_partially_used_tlp_tree.end()) { tlr = it->Reserve(); @@ -659,14 +651,14 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { } // Allocate a new page. - tlp = KThreadLocalPage::Allocate(m_kernel); + tlp = KThreadLocalPage::Allocate(kernel); R_UNLESS(tlp != nullptr, ResultOutOfMemory); ON_RESULT_FAILURE { - KThreadLocalPage::Free(m_kernel, tlp); + KThreadLocalPage::Free(kernel, tlp); }; // Initialize the new page. - R_TRY(tlp->Initialize(m_kernel, this)); + R_TRY(tlp->Initialize(kernel, this)); // Reserve a TLR. tlr = tlp->Reserve(); @@ -674,7 +666,7 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { // Insert into our tree. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); if (tlp->IsAllUsed()) { m_fully_used_tlp_tree.insert(*tlp); } else { @@ -687,12 +679,12 @@ Result KProcess::CreateThreadLocalRegion(KProcessAddress* out) { R_SUCCEED(); } -Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { +Result KProcess::DeleteThreadLocalRegion(KernelCore& kernel, KProcessAddress addr) { KThreadLocalPage* page_to_free = nullptr; // Release the region. { - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Try to find the page in the partially used list. auto it = m_partially_used_tlp_tree.find_key(Common::AlignDown(GetInteger(addr), PageSize)); @@ -729,57 +721,56 @@ Result KProcess::DeleteThreadLocalRegion(KProcessAddress addr) { if (page_to_free != nullptr) { page_to_free->Finalize(); - KThreadLocalPage::Free(m_kernel, page_to_free); + KThreadLocalPage::Free(kernel, page_to_free); } R_SUCCEED(); } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value); + return rl->Reserve(kernel, which, value); } else { return true; } } -bool KProcess::ReserveResource(Svc::LimitableResource which, s64 value, s64 timeout) { +bool KProcess::ReserveResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 timeout) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - return rl->Reserve(which, value, timeout); + return rl->Reserve(kernel, which, value, timeout); } else { return true; } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value); + rl->Release(kernel, which, value); } } -void KProcess::ReleaseResource(Svc::LimitableResource which, s64 value, s64 hint) { +void KProcess::ReleaseResource(KernelCore& kernel, Svc::LimitableResource which, s64 value, s64 hint) { if (KResourceLimit* rl = this->GetResourceLimit(); rl != nullptr) { - rl->Release(which, value, hint); + rl->Release(kernel, which, value, hint); } } -void KProcess::IncrementRunningThreadCount() { +void KProcess::IncrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() >= 0); ++m_num_running_threads; } -void KProcess::DecrementRunningThreadCount() { +void KProcess::DecrementRunningThreadCount(KernelCore& kernel) { ASSERT(m_num_running_threads.load() > 0); - if (const auto prev = m_num_running_threads--; prev == 1) { - this->Terminate(); + this->Terminate(kernel); } } -bool KProcess::EnterUserException() { +bool KProcess::EnterUserException(KernelCore& kernel) { // Get the current thread. - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); ASSERT(this == cur_thread->GetOwnerProcess()); // Check that we haven't already claimed the exception thread. @@ -788,13 +779,13 @@ bool KProcess::EnterUserException() { } // Create the wait queue we'll be using. - ThreadQueueImplForKProcessEnterUserException wait_queue(m_kernel, + ThreadQueueImplForKProcessEnterUserException wait_queue(kernel, std::addressof(m_exception_thread)); // Claim the exception thread. { // Lock the scheduler. - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Check that we're not terminating. if (cur_thread->IsTerminationRequested()) { @@ -804,45 +795,44 @@ bool KProcess::EnterUserException() { // If we don't have an exception thread, we can just claim it directly. if (m_exception_thread == nullptr) { m_exception_thread = cur_thread; - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } // Otherwise, we need to wait until we don't have an exception thread. // Add the current thread as a waiter on the current exception thread. - cur_thread->SetKernelAddressKey( - reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1); - m_exception_thread->AddWaiter(cur_thread); + cur_thread->SetKernelAddressKey(uintptr_t(std::addressof(m_exception_thread)) | 1); + m_exception_thread->AddWaiter(kernel, cur_thread); // Wait to claim the exception thread. - cur_thread->BeginWait(std::addressof(wait_queue)); + cur_thread->BeginWait(kernel, std::addressof(wait_queue)); } // If our wait didn't end due to thread termination, we succeeded. return ResultTerminationRequested != cur_thread->GetWaitResult(); } -bool KProcess::LeaveUserException() { - return this->ReleaseUserException(GetCurrentThreadPointer(m_kernel)); +bool KProcess::LeaveUserException(KernelCore& kernel) { + return this->ReleaseUserException(kernel, GetCurrentThreadPointer(kernel)); } -bool KProcess::ReleaseUserException(KThread* thread) { - KScopedSchedulerLock sl(m_kernel); +bool KProcess::ReleaseUserException(KernelCore& kernel, KThread* thread) { + KScopedSchedulerLock sl(kernel); if (m_exception_thread == thread) { m_exception_thread = nullptr; // Remove waiter thread. bool has_waiters; - if (KThread* next = thread->RemoveKernelWaiterByKey( + if (KThread* next = thread->RemoveKernelWaiterByKey(kernel, std::addressof(has_waiters), reinterpret_cast<uintptr_t>(std::addressof(m_exception_thread)) | 1); next != nullptr) { - next->EndWait(ResultSuccess); + next->EndWait(kernel, ResultSuccess); } - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); return true; } else { @@ -850,19 +840,19 @@ bool KProcess::ReleaseUserException(KThread* thread) { } } -void KProcess::RegisterThread(KThread* thread) { +void KProcess::RegisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.push_back(*thread); } -void KProcess::UnregisterThread(KThread* thread) { +void KProcess::UnregisterThread(KernelCore& kernel, KThread* thread) { KScopedLightLock lk(m_list_lock); m_thread_list.erase(m_thread_list.iterator_to(*thread)); } -size_t KProcess::GetUsedUserPhysicalMemorySize() const { +size_t KProcess::GetUsedUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; const size_t sec_size = this->GetRequiredSecureMemorySizeNonDefault(); @@ -870,7 +860,7 @@ size_t KProcess::GetUsedUserPhysicalMemorySize() const { return norm_size + other_size + sec_size; } -size_t KProcess::GetTotalUserPhysicalMemorySize() const { +size_t KProcess::GetTotalUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -889,18 +879,18 @@ size_t KProcess::GetTotalUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size; } else { - return free_size + this->GetUsedUserPhysicalMemorySize(); + return free_size + this->GetUsedUserPhysicalMemorySize(kernel); } } -size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetUsedNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { const size_t norm_size = m_page_table.GetNormalMemorySize(); const size_t other_size = m_code_size + m_main_thread_stack_size; return norm_size + other_size; } -size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { +size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize(KernelCore& kernel) const { // Get the amount of free and used size. const size_t free_size = m_resource_limit->GetFreeValue(Svc::LimitableResource::PhysicalMemoryMax); @@ -919,11 +909,11 @@ size_t KProcess::GetTotalNonSystemUserPhysicalMemorySize() const { if (used_size + free_size > max_size) { return max_size - this->GetRequiredSecureMemorySizeNonDefault(); } else { - return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(); + return free_size + this->GetUsedNonSystemUserPhysicalMemorySize(kernel); } } -Result KProcess::Run(s32 priority, size_t stack_size) { +Result KProcess::Run(KernelCore& kernel, s32 priority, size_t stack_size) { // Lock ourselves, to prevent concurrent access. KScopedLightLock lk(m_state_lock); @@ -932,7 +922,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(state == State::Created || state == State::CreatedAttached, ResultInvalidState); // Place a tentative reservation of a thread for this process. - KScopedResourceReservation thread_reservation(this, Svc::LimitableResource::ThreadCountMax); + KScopedResourceReservation thread_reservation(kernel, this, Svc::LimitableResource::ThreadCountMax); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); // Ensure that we haven't already allocated stack. @@ -944,7 +934,7 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_UNLESS(stack_size + m_code_size >= m_code_size, ResultOutOfMemory); // Place a tentative reservation of memory for our new stack. - KScopedResourceReservation mem_reservation(this, Svc::LimitableResource::PhysicalMemoryMax, + KScopedResourceReservation mem_reservation(kernel, this, Svc::LimitableResource::PhysicalMemoryMax, stack_size); R_UNLESS(mem_reservation.Succeeded(), ResultLimitReached); @@ -974,29 +964,29 @@ Result KProcess::Run(s32 priority, size_t stack_size) { (m_main_thread_stack_size + m_code_size))); // Initialize our handle table. - R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize())); + R_TRY(this->InitializeHandleTable(kernel, m_capabilities.GetHandleTableSize())); ON_RESULT_FAILURE_2 { - this->FinalizeHandleTable(); + this->FinalizeHandleTable(kernel); }; // Create a new thread for the process. - KThread* main_thread = KThread::Create(m_kernel); + KThread* main_thread = KThread::Create(kernel); R_UNLESS(main_thread != nullptr, ResultOutOfResource); SCOPE_EXIT { - main_thread->Close(); + main_thread->Close(kernel); }; // Initialize the thread. - R_TRY(KThread::InitializeUserThread(m_kernel.System(), main_thread, this->GetEntryPoint(), 0, + R_TRY(KThread::InitializeUserThread(kernel.System(), main_thread, this->GetEntryPoint(), 0, stack_top, priority, m_ideal_core_id, this)); // Register the thread, and commit our reservation. - KThread::Register(m_kernel, main_thread); + KThread::Register(kernel, main_thread); thread_reservation.Commit(); // Add the thread to our handle table. Handle thread_handle; - R_TRY(m_handle_table.Add(std::addressof(thread_handle), main_thread)); + R_TRY(m_handle_table.Add(kernel, std::addressof(thread_handle), main_thread)); // Set the thread arguments. Two distinct entry conventions: // * Kernel/NSO entry (no homebrew ABI): x0 = 0, x1 = thread_handle @@ -1024,21 +1014,21 @@ Result KProcess::Run(s32 priority, size_t stack_size) { this->GetMemory().Write32(GetInteger(main_thread->GetTlsAddress()) + 0x110, thread_handle); // Update our state. - this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached); + this->ChangeState(kernel, (state == State::Created) ? State::Running : State::RunningAttached); ON_RESULT_FAILURE_2 { - this->ChangeState(state); + this->ChangeState(kernel, state); }; // Suspend for debug, if we should. - if (m_kernel.System().DebuggerEnabled()) { - main_thread->RequestSuspend(SuspendType::Debug); + if (kernel.System().DebuggerEnabled()) { + main_thread->RequestSuspend(kernel, SuspendType::Debug); } // Run our thread. - R_TRY(main_thread->Run()); + R_TRY(main_thread->Run(kernel)); // Open a reference to represent that we're running. - this->Open(); + this->Open(kernel); // We succeeded! Commit our memory reservation. mem_reservation.Commit(); @@ -1046,10 +1036,10 @@ Result KProcess::Run(s32 priority, size_t stack_size) { R_SUCCEED(); } -Result KProcess::Reset() { +Result KProcess::Reset(KernelCore& kernel) { // Lock the process and the scheduler. KScopedLightLock lk(m_state_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate that we're in a state that we can reset. R_UNLESS(m_state != State::Terminated, ResultInvalidState); @@ -1060,11 +1050,11 @@ Result KProcess::Reset() { R_SUCCEED(); } -Result KProcess::SetActivity(Svc::ProcessActivity activity) { +Result KProcess::SetActivity(KernelCore& kernel, Svc::ProcessActivity activity) { // Lock ourselves and the scheduler. KScopedLightLock lk(m_state_lock); KScopedLightLock list_lk(m_list_lock); - KScopedSchedulerLock sl(m_kernel); + KScopedSchedulerLock sl(kernel); // Validate our state. R_UNLESS(m_state != State::Terminating, ResultInvalidState); @@ -1078,7 +1068,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Suspend all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->RequestSuspend(SuspendType::Process); + it->RequestSuspend(kernel, SuspendType::Process); } // Set ourselves as suspended. @@ -1092,7 +1082,7 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { // Resume all threads. auto end = this->GetThreadList().end(); for (auto it = this->GetThreadList().begin(); it != end; ++it) { - it->Resume(SuspendType::Process); + it->Resume(kernel, SuspendType::Process); } // Set ourselves as resumed. @@ -1102,54 +1092,54 @@ Result KProcess::SetActivity(Svc::ProcessActivity activity) { R_SUCCEED(); } -void KProcess::PinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::PinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // If the thread isn't terminated, pin it. if (!cur_thread->IsTerminationRequested()) { // Pin it. this->PinThread(core_id, cur_thread); - cur_thread->Pin(core_id); + cur_thread->Pin(kernel, core_id); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } } -void KProcess::UnpinCurrentThread() { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinCurrentThread(KernelCore& kernel) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the current thread. - const s32 core_id = GetCurrentCoreId(m_kernel); - KThread* cur_thread = GetCurrentThreadPointer(m_kernel); + const s32 core_id = GetCurrentCoreId(kernel); + KThread* cur_thread = GetCurrentThreadPointer(kernel); // Unpin it. - cur_thread->Unpin(); + cur_thread->Unpin(kernel); this->UnpinThread(core_id, cur_thread); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -void KProcess::UnpinThread(KThread* thread) { - ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(m_kernel)); +void KProcess::UnpinThread(KernelCore& kernel, KThread* thread) { + ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel)); // Get the thread's core id. const auto core_id = thread->GetActiveCore(); // Unpin it. this->UnpinThread(core_id, thread); - thread->Unpin(); + thread->Unpin(kernel); // An update is needed. - KScheduler::SetSchedulerUpdateNeeded(m_kernel); + KScheduler::SetSchedulerUpdateNeeded(kernel); } -Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, +Result KProcess::GetThreadList(KernelCore& kernel, s32* out_num_threads, KProcessAddress out_thread_ids, s32 max_out_count) { auto& memory = this->GetMemory(); @@ -1179,7 +1169,7 @@ Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ R_SUCCEED(); } -void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {} +void KProcess::Switch(KernelCore& kernel, KProcess* cur_process, KProcess* next_process) {} KProcess::KProcess(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer(kernel) @@ -1195,16 +1185,16 @@ KProcess::KProcess(KernelCore& kernel) KProcess::~KProcess() = default; -Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { +Result KProcess::LoadFromMetadata(KernelCore& kernel, const FileSys::ProgramMetadata& metadata, std::size_t code_size, KProcessAddress aslr_space_start, size_t aslr_space_offset) { // Create a resource limit for the process. const auto pool = static_cast<KMemoryManager::Pool>(metadata.GetPoolPartition()); - const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool); + const auto physical_memory_size = kernel.MemoryManager().GetSize(pool); auto* res_limit = - Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size); + Kernel::CreateResourceLimitForProcess(kernel.System(), physical_memory_size); // Ensure we maintain a clean state on exit. SCOPE_EXIT { - res_limit->Close(); + res_limit->Close(kernel); }; // Declare flags and code address. @@ -1263,22 +1253,20 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: std::memcpy(params.name.data(), name.data(), sizeof(params.name)); // Initialize for application process. - R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool, - aslr_space_start)); + R_TRY(this->Initialize(kernel, params, metadata.GetKernelCapabilities(), res_limit, pool, aslr_space_start)); // Assign remaining properties. m_ideal_core_id = metadata.GetMainThreadCore(); // Set up emulation context. - this->InitializeInterfaces(); + this->InitializeInterfaces(kernel); // We succeeded. R_SUCCEED(); } -void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { - const auto ReprotectSegment = [&](const CodeSet::Segment& segment, - Svc::MemoryPermission permission) { +void KProcess::LoadModule(KernelCore& kernel, CodeSet code_set, KProcessAddress base_addr) { + const auto ReprotectSegment = [&](const CodeSet::Segment& segment, Svc::MemoryPermission permission) { m_page_table.SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); }; @@ -1292,7 +1280,7 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { const auto& patch = code_set.PatchSegment(); const auto& post_patch = code_set.PostPatchSegment(); if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) { - auto& buffer = m_kernel.System().DeviceMemory().buffer; + auto& buffer = kernel.System().DeviceMemory().buffer; const auto& code = code_set.CodeSegment(); buffer.Protect(GetInteger(base_addr + code.addr), code.size, Common::MemoryPermission::Read | Common::MemoryPermission::Execute); @@ -1311,32 +1299,32 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) { #endif } -void KProcess::InitializeInterfaces() { +void KProcess::InitializeInterfaces(KernelCore& kernel) { m_exclusive_monitor = Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); #ifdef HAS_NCE if (this->IsApplication() && Settings::IsNceEnabled()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) - m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(m_kernel.System(), true, i); + m_arm_interfaces[i] = std::make_unique<Core::ArmNce>(kernel.System(), true, i); } else #endif if (this->Is64Bit()) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic64>( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast<Core::DynarmicExclusiveMonitor&>(*m_exclusive_monitor), i); } } else { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { m_arm_interfaces[i] = std::make_unique<Core::ArmDynarmic32>( - m_kernel.System(), m_kernel.IsMulticore(), this, + kernel.System(), kernel.IsMulticore(), this, static_cast<Core::DynarmicExclusiveMonitor&>(*m_exclusive_monitor), i); } } } -bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::InsertWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.type == DebugWatchpointType::None; })}; @@ -1358,7 +1346,7 @@ bool KProcess::InsertWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointT return true; } -bool KProcess::RemoveWatchpoint(KProcessAddress addr, u64 size, DebugWatchpointType type) { +bool KProcess::RemoveWatchpoint(KernelCore& kernel, KProcessAddress addr, u64 size, DebugWatchpointType type) { const auto watch{std::find_if(m_watchpoints.begin(), m_watchpoints.end(), [&](const auto& wp) { return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; })}; |
