summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/kernel.cpp81
1 files changed, 48 insertions, 33 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 45e86a677..2e4e4cb1c 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -14,6 +14,7 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
+#include "common/scope_exit.h"
#include "common/thread.h"
#include "common/thread_worker.h"
#include "core/arm/arm_interface.h"
@@ -83,12 +84,16 @@ struct KernelCore::Impl {
}
void InitializeCores() {
- for (auto& core : cores) {
- core.Initialize(current_process->Is64BitProcess());
+ 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);
}
}
void Shutdown() {
+ is_shutting_down.store(true, std::memory_order_relaxed);
+ SCOPE_EXIT({ is_shutting_down.store(false, std::memory_order_relaxed); });
+
process_list.clear();
// Close all open server ports.
@@ -123,15 +128,6 @@ struct KernelCore::Impl {
next_user_process_id = KProcess::ProcessIDMin;
next_thread_id = 1;
- for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
- if (suspend_threads[core_id]) {
- suspend_threads[core_id]->Close();
- suspend_threads[core_id] = nullptr;
- }
-
- schedulers[core_id].reset();
- }
-
cores.clear();
global_handle_table->Finalize();
@@ -159,6 +155,16 @@ struct KernelCore::Impl {
CleanupObject(time_shared_mem);
CleanupObject(system_resource_limit);
+ for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
+ if (suspend_threads[core_id]) {
+ suspend_threads[core_id]->Close();
+ suspend_threads[core_id] = nullptr;
+ }
+
+ schedulers[core_id]->Finalize();
+ schedulers[core_id].reset();
+ }
+
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
@@ -245,13 +251,11 @@ struct KernelCore::Impl {
KScopedSchedulerLock lock(kernel);
global_scheduler_context->PreemptThreads();
}
- const auto time_interval = std::chrono::nanoseconds{
- Core::Timing::msToCycles(std::chrono::milliseconds(10))};
+ const auto time_interval = std::chrono::nanoseconds{std::chrono::milliseconds(10)};
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
});
- const auto time_interval =
- std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))};
+ const auto time_interval = std::chrono::nanoseconds{std::chrono::milliseconds(10)};
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
}
@@ -267,14 +271,6 @@ struct KernelCore::Impl {
void MakeCurrentProcess(KProcess* process) {
current_process = process;
- if (process == nullptr) {
- return;
- }
-
- const u32 core_id = GetCurrentHostThreadID();
- if (core_id < Core::Hardware::NUM_CPU_CORES) {
- system.Memory().SetCurrentPageTable(*process, core_id);
- }
}
static inline thread_local u32 host_thread_id = UINT32_MAX;
@@ -344,7 +340,16 @@ struct KernelCore::Impl {
is_phantom_mode_for_singlecore = value;
}
+ bool IsShuttingDown() const {
+ return is_shutting_down.load(std::memory_order_relaxed);
+ }
+
KThread* GetCurrentEmuThread() {
+ // If we are shutting down the kernel, none of this is relevant anymore.
+ if (IsShuttingDown()) {
+ return {};
+ }
+
const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
return GetHostDummyThread();
@@ -760,6 +765,7 @@ struct KernelCore::Impl {
std::vector<std::unique_ptr<KThread>> dummy_threads;
bool is_multicore{};
+ std::atomic_bool is_shutting_down{};
bool is_phantom_mode_for_singlecore{};
u32 single_core_thread_id{};
@@ -845,16 +851,20 @@ const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
return impl->cores[id];
}
+size_t KernelCore::CurrentPhysicalCoreIndex() const {
+ const u32 core_id = impl->GetCurrentHostThreadID();
+ if (core_id >= Core::Hardware::NUM_CPU_CORES) {
+ return Core::Hardware::NUM_CPU_CORES - 1;
+ }
+ return core_id;
+}
+
Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
- u32 core_id = impl->GetCurrentHostThreadID();
- ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
- return impl->cores[core_id];
+ return impl->cores[CurrentPhysicalCoreIndex()];
}
const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
- u32 core_id = impl->GetCurrentHostThreadID();
- ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
- return impl->cores[core_id];
+ return impl->cores[CurrentPhysicalCoreIndex()];
}
Kernel::KScheduler* KernelCore::CurrentScheduler() {
@@ -1057,6 +1067,9 @@ void KernelCore::Suspend(bool in_suspention) {
impl->suspend_threads[core_id]->SetState(state);
impl->suspend_threads[core_id]->SetWaitReasonForDebugging(
ThreadWaitReasonForDebugging::Suspended);
+ if (!should_suspend) {
+ impl->suspend_threads[core_id]->DisableDispatch();
+ }
}
}
}
@@ -1065,19 +1078,21 @@ bool KernelCore::IsMulticore() const {
return impl->is_multicore;
}
+bool KernelCore::IsShuttingDown() const {
+ return impl->IsShuttingDown();
+}
+
void KernelCore::ExceptionalExit() {
exception_exited = true;
Suspend(true);
}
void KernelCore::EnterSVCProfile() {
- std::size_t core = impl->GetCurrentHostThreadID();
- impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
+ impl->svc_ticks[CurrentPhysicalCoreIndex()] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
}
void KernelCore::ExitSVCProfile() {
- std::size_t core = impl->GetCurrentHostThreadID();
- MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
+ MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
}
std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {