summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_process.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_process.cpp (renamed from src/core/hle/kernel/process.cpp)149
1 files changed, 98 insertions, 51 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/k_process.cpp
index e35deb8e2..bdcbaeeaa 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -17,13 +17,14 @@
#include "core/hle/kernel/code_set.h"
#include "core/hle/kernel/k_memory_block_manager.h"
#include "core/hle/kernel/k_page_table.h"
+#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_resource_reservation.h"
+#include "core/hle/kernel/k_shared_memory.h"
#include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/process.h"
#include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h"
@@ -37,17 +38,20 @@ namespace {
* @param owner_process The parent process for the main thread
* @param priority The priority to give the main thread
*/
-void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) {
+void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) {
const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1));
- auto thread_res =
- KThread::CreateUserThread(system, ThreadType::User, "main", entry_point, priority, 0,
- owner_process.GetIdealCoreId(), stack_top, &owner_process);
- std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap();
+ KThread* thread = KThread::Create(system.Kernel());
+ ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority,
+ owner_process.GetIdealCoreId(), &owner_process)
+ .IsSuccess());
// Register 1 must be a handle to the main thread
- const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
+ Handle thread_handle{};
+ owner_process.GetHandleTable().Add(&thread_handle, thread);
+
+ thread->SetName("main");
thread->GetContext32().cpu_registers[0] = 0;
thread->GetContext64().cpu_registers[0] = 0;
thread->GetContext32().cpu_registers[1] = thread_handle;
@@ -114,11 +118,11 @@ private:
std::bitset<num_slot_entries> is_slot_used;
};
-std::shared_ptr<Process> Process::Create(Core::System& system, std::string name, ProcessType type) {
+ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name,
+ ProcessType type) {
auto& kernel = system.Kernel();
- std::shared_ptr<Process> process = std::make_shared<Process>(system);
- process->name = std::move(name);
+ process->name = std::move(process_name);
process->resource_limit = kernel.GetSystemResourceLimit();
process->status = ProcessStatus::Created;
@@ -126,6 +130,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
: kernel.CreateNewUserProcessID();
process->capabilities.InitializeForMetadatalessProcess();
+ process->is_initialized = true;
std::mt19937 rng(Settings::values.rng_seed.GetValue().value_or(std::time(nullptr)));
std::uniform_int_distribution<u64> distribution;
@@ -133,14 +138,18 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
[&] { return distribution(rng); });
kernel.AppendNewProcess(process);
- return process;
+
+ // Open a reference to the resource limit.
+ process->resource_limit->Open();
+
+ return RESULT_SUCCESS;
}
-std::shared_ptr<KResourceLimit> Process::GetResourceLimit() const {
+KResourceLimit* KProcess::GetResourceLimit() const {
return resource_limit;
}
-void Process::IncrementThreadCount() {
+void KProcess::IncrementThreadCount() {
ASSERT(num_threads >= 0);
num_created_threads++;
@@ -149,7 +158,7 @@ void Process::IncrementThreadCount() {
}
}
-void Process::DecrementThreadCount() {
+void KProcess::DecrementThreadCount() {
ASSERT(num_threads > 0);
if (const auto count = --num_threads; count == 0) {
@@ -157,31 +166,34 @@ void Process::DecrementThreadCount() {
}
}
-u64 Process::GetTotalPhysicalMemoryAvailable() const {
+u64 KProcess::GetTotalPhysicalMemoryAvailable() const {
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
main_thread_stack_size};
- ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
+ if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
+ capacity != pool_size) {
+ LOG_WARNING(Kernel, "capacity {} != application pool size {}", capacity, pool_size);
+ }
if (capacity < memory_usage_capacity) {
return capacity;
}
return memory_usage_capacity;
}
-u64 Process::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const {
+u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const {
return GetTotalPhysicalMemoryAvailable() - GetSystemResourceSize();
}
-u64 Process::GetTotalPhysicalMemoryUsed() const {
+u64 KProcess::GetTotalPhysicalMemoryUsed() const {
return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() +
GetSystemResourceSize();
}
-u64 Process::GetTotalPhysicalMemoryUsedWithoutSystemResource() const {
+u64 KProcess::GetTotalPhysicalMemoryUsedWithoutSystemResource() const {
return GetTotalPhysicalMemoryUsed() - GetSystemResourceUsage();
}
-bool Process::ReleaseUserException(KThread* thread) {
+bool KProcess::ReleaseUserException(KThread* thread) {
KScopedSchedulerLock sl{kernel};
if (exception_thread == thread) {
@@ -206,7 +218,7 @@ bool Process::ReleaseUserException(KThread* thread) {
}
}
-void Process::PinCurrentThread() {
+void KProcess::PinCurrentThread() {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Get the current thread.
@@ -221,7 +233,7 @@ void Process::PinCurrentThread() {
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
-void Process::UnpinCurrentThread() {
+void KProcess::UnpinCurrentThread() {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
// Get the current thread.
@@ -236,15 +248,39 @@ void Process::UnpinCurrentThread() {
KScheduler::SetSchedulerUpdateNeeded(kernel);
}
-void Process::RegisterThread(const KThread* thread) {
+ResultCode KProcess::AddSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address,
+ [[maybe_unused]] size_t size) {
+ // Lock ourselves, to prevent concurrent access.
+ KScopedLightLock lk(state_lock);
+
+ // TODO(bunnei): Manage KSharedMemoryInfo list here.
+
+ // Open a reference to the shared memory.
+ shmem->Open();
+
+ return RESULT_SUCCESS;
+}
+
+void KProcess::RemoveSharedMemory(KSharedMemory* shmem, [[maybe_unused]] VAddr address,
+ [[maybe_unused]] size_t size) {
+ // Lock ourselves, to prevent concurrent access.
+ KScopedLightLock lk(state_lock);
+
+ // TODO(bunnei): Manage KSharedMemoryInfo list here.
+
+ // Close a reference to the shared memory.
+ shmem->Close();
+}
+
+void KProcess::RegisterThread(const KThread* thread) {
thread_list.push_back(thread);
}
-void Process::UnregisterThread(const KThread* thread) {
+void KProcess::UnregisterThread(const KThread* thread) {
thread_list.remove(thread);
}
-ResultCode Process::Reset() {
+ResultCode KProcess::Reset() {
// Lock the process and the scheduler.
KScopedLightLock lk(state_lock);
KScopedSchedulerLock sl{kernel};
@@ -258,8 +294,8 @@ ResultCode Process::Reset() {
return RESULT_SUCCESS;
}
-ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
- std::size_t code_size) {
+ResultCode KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
+ std::size_t code_size) {
program_id = metadata.GetTitleID();
ideal_core = metadata.GetMainThreadCore();
is_64bit_process = metadata.Is64BitProgram();
@@ -271,7 +307,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
if (!memory_reservation.Succeeded()) {
LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
code_size + system_resource_size);
- return ResultResourceLimitedExceeded;
+ return ResultLimitReached;
}
// Initialize proces address space
if (const ResultCode result{
@@ -318,10 +354,10 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
tls_region_address = CreateTLSRegion();
memory_reservation.Commit();
- return handle_table.SetSize(capabilities.GetHandleTableSize());
+ return handle_table.Initialize(capabilities.GetHandleTableSize());
}
-void Process::Run(s32 main_thread_priority, u64 stack_size) {
+void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
AllocateMainThreadStack(stack_size);
resource_limit->Reserve(LimitableResource::Threads, 1);
resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
@@ -331,18 +367,18 @@ void Process::Run(s32 main_thread_priority, u64 stack_size) {
ChangeStatus(ProcessStatus::Running);
- SetupMainThread(system, *this, main_thread_priority, main_thread_stack_top);
+ SetupMainThread(kernel.System(), *this, main_thread_priority, main_thread_stack_top);
}
-void Process::PrepareForTermination() {
+void KProcess::PrepareForTermination() {
ChangeStatus(ProcessStatus::Exiting);
- const auto stop_threads = [this](const std::vector<std::shared_ptr<KThread>>& thread_list) {
- for (auto& thread : thread_list) {
+ const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) {
+ for (auto& thread : in_thread_list) {
if (thread->GetOwnerProcess() != this)
continue;
- if (thread.get() == kernel.CurrentScheduler()->GetCurrentThread())
+ if (thread == kernel.CurrentScheduler()->GetCurrentThread())
continue;
// TODO(Subv): When are the other running/ready threads terminated?
@@ -353,7 +389,7 @@ void Process::PrepareForTermination() {
}
};
- stop_threads(system.GlobalSchedulerContext().GetThreadList());
+ stop_threads(kernel.System().GlobalSchedulerContext().GetThreadList());
FreeTLSRegion(tls_region_address);
tls_region_address = 0;
@@ -366,6 +402,16 @@ void Process::PrepareForTermination() {
ChangeStatus(ProcessStatus::Exited);
}
+void KProcess::Finalize() {
+ // Release memory to the resource limit.
+ if (resource_limit != nullptr) {
+ resource_limit->Close();
+ }
+
+ // Perform inherited finalization.
+ KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize();
+}
+
/**
* Attempts to find a TLS page that contains a free slot for
* use by a thread.
@@ -379,8 +425,8 @@ static auto FindTLSPageWithAvailableSlots(std::vector<TLSPage>& tls_pages) {
[](const auto& page) { return page.HasAvailableSlots(); });
}
-VAddr Process::CreateTLSRegion() {
- KScopedSchedulerLock lock(system.Kernel());
+VAddr KProcess::CreateTLSRegion() {
+ KScopedSchedulerLock lock(kernel);
if (auto tls_page_iter{FindTLSPageWithAvailableSlots(tls_pages)};
tls_page_iter != tls_pages.cend()) {
return *tls_page_iter->ReserveSlot();
@@ -391,7 +437,7 @@ VAddr Process::CreateTLSRegion() {
const VAddr start{page_table->GetKernelMapRegionStart()};
const VAddr size{page_table->GetKernelMapRegionEnd() - start};
- const PAddr tls_map_addr{system.DeviceMemory().GetPhysicalAddr(tls_page_ptr)};
+ const PAddr tls_map_addr{kernel.System().DeviceMemory().GetPhysicalAddr(tls_page_ptr)};
const VAddr tls_page_addr{page_table
->AllocateAndMapMemory(1, PageSize, true, start, size / PageSize,
KMemoryState::ThreadLocal,
@@ -410,8 +456,8 @@ VAddr Process::CreateTLSRegion() {
return *reserve_result;
}
-void Process::FreeTLSRegion(VAddr tls_address) {
- KScopedSchedulerLock lock(system.Kernel());
+void KProcess::FreeTLSRegion(VAddr tls_address) {
+ KScopedSchedulerLock lock(kernel);
const VAddr aligned_address = Common::AlignDown(tls_address, Core::Memory::PAGE_SIZE);
auto iter =
std::find_if(tls_pages.begin(), tls_pages.end(), [aligned_address](const auto& page) {
@@ -425,33 +471,34 @@ void Process::FreeTLSRegion(VAddr tls_address) {
iter->ReleaseSlot(tls_address);
}
-void Process::LoadModule(CodeSet code_set, VAddr base_addr) {
+void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
std::lock_guard lock{HLE::g_hle_lock};
const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
KMemoryPermission permission) {
page_table->SetCodeMemoryPermission(segment.addr + base_addr, segment.size, permission);
};
- system.Memory().WriteBlock(*this, base_addr, code_set.memory.data(), code_set.memory.size());
+ kernel.System().Memory().WriteBlock(*this, base_addr, code_set.memory.data(),
+ code_set.memory.size());
ReprotectSegment(code_set.CodeSegment(), KMemoryPermission::ReadAndExecute);
ReprotectSegment(code_set.RODataSegment(), KMemoryPermission::Read);
ReprotectSegment(code_set.DataSegment(), KMemoryPermission::ReadAndWrite);
}
-bool Process::IsSignaled() const {
+bool KProcess::IsSignaled() const {
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
return is_signaled;
}
-Process::Process(Core::System& system)
- : KSynchronizationObject{system.Kernel()}, page_table{std::make_unique<KPageTable>(system)},
- handle_table{system.Kernel()}, address_arbiter{system}, condition_var{system},
- state_lock{system.Kernel()}, system{system} {}
+KProcess::KProcess(KernelCore& kernel_)
+ : KAutoObjectWithSlabHeapAndContainer{kernel_},
+ page_table{std::make_unique<KPageTable>(kernel_.System())}, handle_table{kernel_},
+ address_arbiter{kernel_.System()}, condition_var{kernel_.System()}, state_lock{kernel_} {}
-Process::~Process() = default;
+KProcess::~KProcess() = default;
-void Process::ChangeStatus(ProcessStatus new_status) {
+void KProcess::ChangeStatus(ProcessStatus new_status) {
if (status == new_status) {
return;
}
@@ -461,7 +508,7 @@ void Process::ChangeStatus(ProcessStatus new_status) {
NotifyAvailable();
}
-ResultCode Process::AllocateMainThreadStack(std::size_t stack_size) {
+ResultCode KProcess::AllocateMainThreadStack(std::size_t stack_size) {
ASSERT(stack_size);
// The kernel always ensures that the given stack size is page aligned.