summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp99
1 files changed, 64 insertions, 35 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1fb25f221..3a68a5633 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -29,6 +29,7 @@
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
+#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_page_buffer.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
@@ -84,6 +85,7 @@ struct KernelCore::Impl {
InitializeShutdownThreads();
InitializePhysicalCores();
InitializePreemption(kernel);
+ InitializeGlobalData(kernel);
// Initialize the Dynamic Slab Heaps.
{
@@ -102,13 +104,13 @@ struct KernelCore::Impl {
void InitializeCores() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
- cores[core_id]->Initialize((*current_process).Is64BitProcess());
- system.Memory().SetCurrentPageTable(*current_process, core_id);
+ cores[core_id]->Initialize((*application_process).Is64BitProcess());
+ system.Memory().SetCurrentPageTable(*application_process, core_id);
}
}
- void CloseCurrentProcess() {
- KProcess* old_process = current_process.exchange(nullptr);
+ void CloseApplicationProcess() {
+ KProcess* old_process = application_process.exchange(nullptr);
if (old_process == nullptr) {
return;
}
@@ -182,7 +184,7 @@ struct KernelCore::Impl {
}
}
- CloseCurrentProcess();
+ CloseApplicationProcess();
// Track kernel objects that were not freed on shutdown
{
@@ -194,6 +196,8 @@ struct KernelCore::Impl {
}
}
+ object_name_global_data.reset();
+
// Ensure that the object list container is finalized and properly shutdown.
global_object_list_container->Finalize();
global_object_list_container.reset();
@@ -363,8 +367,12 @@ struct KernelCore::Impl {
}
}
- void MakeCurrentProcess(KProcess* process) {
- current_process = process;
+ void InitializeGlobalData(KernelCore& kernel) {
+ object_name_global_data = std::make_unique<KObjectNameGlobalData>(kernel);
+ }
+
+ void MakeApplicationProcess(KProcess* process) {
+ application_process = process;
}
static inline thread_local u32 host_thread_id = UINT32_MAX;
@@ -821,7 +829,7 @@ struct KernelCore::Impl {
// Lists all processes that exist in the current session.
std::vector<KProcess*> process_list;
- std::atomic<KProcess*> current_process{};
+ std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
@@ -838,6 +846,8 @@ struct KernelCore::Impl {
std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
+ std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
+
/// Map of named ports managed by the kernel, which can be retrieved using
/// the ConnectToPort SVC.
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
@@ -941,20 +951,20 @@ void KernelCore::AppendNewProcess(KProcess* process) {
impl->process_list.push_back(process);
}
-void KernelCore::MakeCurrentProcess(KProcess* process) {
- impl->MakeCurrentProcess(process);
+void KernelCore::MakeApplicationProcess(KProcess* process) {
+ impl->MakeApplicationProcess(process);
}
-KProcess* KernelCore::CurrentProcess() {
- return impl->current_process;
+KProcess* KernelCore::ApplicationProcess() {
+ return impl->application_process;
}
-const KProcess* KernelCore::CurrentProcess() const {
- return impl->current_process;
+const KProcess* KernelCore::ApplicationProcess() const {
+ return impl->application_process;
}
-void KernelCore::CloseCurrentProcess() {
- impl->CloseCurrentProcess();
+void KernelCore::CloseApplicationProcess() {
+ impl->CloseApplicationProcess();
}
const std::vector<KProcess*>& KernelCore::GetProcessList() const {
@@ -1138,6 +1148,10 @@ void KernelCore::SetCurrentEmuThread(KThread* thread) {
impl->SetCurrentEmuThread(thread);
}
+KObjectNameGlobalData& KernelCore::ObjectNameGlobalData() {
+ return *impl->object_name_global_data;
+}
+
KMemoryManager& KernelCore::MemoryManager() {
return *impl->memory_manager;
}
@@ -1146,6 +1160,14 @@ const KMemoryManager& KernelCore::MemoryManager() const {
return *impl->memory_manager;
}
+KSystemResource& KernelCore::GetAppSystemResource() {
+ return *impl->app_system_resource;
+}
+
+const KSystemResource& KernelCore::GetAppSystemResource() const {
+ return *impl->app_system_resource;
+}
+
KSystemResource& KernelCore::GetSystemSystemResource() {
return *impl->sys_system_resource;
}
@@ -1194,32 +1216,39 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
return *impl->hidbus_shared_mem;
}
-void KernelCore::Suspend(bool suspended) {
+void KernelCore::SuspendApplication(bool suspended) {
const bool should_suspend{exception_exited || suspended};
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
- std::vector<KScopedAutoObject<KThread>> process_threads;
- {
- KScopedSchedulerLock sl{*this};
+ // Get the application process.
+ KScopedAutoObject<KProcess> process = ApplicationProcess();
+ if (process.IsNull()) {
+ return;
+ }
- if (auto* process = CurrentProcess(); process != nullptr) {
- process->SetActivity(activity);
+ // Set the new activity.
+ process->SetActivity(activity);
- if (!should_suspend) {
- // Runnable now; no need to wait.
- return;
- }
+ // Wait for process execution to stop.
+ bool must_wait{should_suspend};
- for (auto* thread : process->GetThreadList()) {
- process_threads.emplace_back(thread);
+ // KernelCore::SuspendApplication must be called from locked context,
+ // or we could race another call to SetActivity, interfering with waiting.
+ while (must_wait) {
+ KScopedSchedulerLock sl{*this};
+
+ // Assume that all threads have finished running.
+ must_wait = false;
+
+ for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
+ if (Scheduler(i).GetSchedulerCurrentThread()->GetOwnerProcess() ==
+ process.GetPointerUnsafe()) {
+ // A thread has not finished running yet.
+ // Continue waiting.
+ must_wait = true;
}
}
}
-
- // Wait for execution to stop.
- for (auto& thread : process_threads) {
- thread->WaitUntilSuspended();
- }
}
void KernelCore::ShutdownCores() {
@@ -1238,9 +1267,9 @@ bool KernelCore::IsShuttingDown() const {
return impl->IsShuttingDown();
}
-void KernelCore::ExceptionalExit() {
+void KernelCore::ExceptionalExitApplication() {
exception_exited = true;
- Suspend(true);
+ SuspendApplication(true);
}
void KernelCore::EnterSVCProfile() {