aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/k_process.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/k_process.cpp')
-rw-r--r--src/core/hle/kernel/k_process.cpp370
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;
})};