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.cpp109
1 files changed, 65 insertions, 44 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 47b760a9c..b77723503 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -91,9 +91,9 @@ struct KernelCore::Impl {
pt_heap_region.GetSize());
}
- RegisterHostThread();
+ RegisterHostThread(nullptr);
- default_service_thread = CreateServiceThread(kernel, "DefaultServiceThread");
+ default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");
}
void InitializeCores() {
@@ -229,18 +229,22 @@ struct KernelCore::Impl {
const auto kernel_size{sizes.second};
// If setting the default system values fails, then something seriously wrong has occurred.
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
+ ASSERT(
+ system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, total_size)
+ .IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800)
.IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900)
.IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
- system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200)
+ .IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133)
+ .IsSuccess());
+ system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size);
// Reserve secure applet memory, introduced in firmware 5.0.0
constexpr u64 secure_applet_memory_size{4_MiB};
- ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
+ ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax,
secure_applet_memory_size));
}
@@ -373,15 +377,18 @@ struct KernelCore::Impl {
}
// Gets the dummy KThread for the caller, allocating a new one if this is the first time
- KThread* GetHostDummyThread() {
+ KThread* GetHostDummyThread(KThread* existing_thread) {
auto initialize = [this](KThread* thread) {
- ASSERT(KThread::InitializeDummyThread(thread).IsSuccess());
+ ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
return thread;
};
- thread_local auto raw_thread = KThread(system.Kernel());
- thread_local auto thread = initialize(&raw_thread);
+ thread_local KThread raw_thread{system.Kernel()};
+ thread_local KThread* thread = nullptr;
+ if (thread == nullptr) {
+ thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread;
+ }
return thread;
}
@@ -396,9 +403,9 @@ struct KernelCore::Impl {
}
/// Registers a new host thread by allocating a host thread ID for it
- void RegisterHostThread() {
+ void RegisterHostThread(KThread* existing_thread) {
[[maybe_unused]] const auto this_id = GetHostThreadId();
- [[maybe_unused]] const auto dummy_thread = GetHostDummyThread();
+ [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);
}
[[nodiscard]] u32 GetCurrentHostThreadID() {
@@ -429,7 +436,7 @@ struct KernelCore::Impl {
KThread* GetCurrentEmuThread() {
const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
- return GetHostDummyThread();
+ return GetHostDummyThread(nullptr);
}
return current_thread;
@@ -779,33 +786,31 @@ struct KernelCore::Impl {
search->second(system.ServiceManager(), server_port);
}
- std::weak_ptr<Kernel::ServiceThread> CreateServiceThread(KernelCore& kernel,
- const std::string& name) {
- auto service_thread = std::make_shared<Kernel::ServiceThread>(kernel, name);
+ Kernel::ServiceThread& CreateServiceThread(KernelCore& kernel, const std::string& name) {
+ auto* ptr = new ServiceThread(kernel, name);
service_threads_manager.QueueWork(
- [this, service_thread]() { service_threads.emplace(service_thread); });
+ [this, ptr]() { service_threads.emplace(ptr, std::unique_ptr<ServiceThread>(ptr)); });
- return service_thread;
+ return *ptr;
}
- void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
- if (auto strong_ptr = service_thread.lock()) {
- if (strong_ptr == default_service_thread.lock()) {
- // Nothing to do here, the service is using default_service_thread, which will be
- // released on shutdown.
- return;
- }
+ void ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
+ auto* ptr = &service_thread;
- service_threads_manager.QueueWork(
- [this, strong_ptr{std::move(strong_ptr)}]() { service_threads.erase(strong_ptr); });
+ if (ptr == default_service_thread) {
+ // Nothing to do here, the service is using default_service_thread, which will be
+ // released on shutdown.
+ return;
}
+
+ service_threads_manager.QueueWork([this, ptr]() { service_threads.erase(ptr); });
}
void ClearServiceThreads() {
service_threads_manager.QueueWork([this] {
service_threads.clear();
- default_service_thread.reset();
+ default_service_thread = nullptr;
service_thread_barrier.Sync();
});
service_thread_barrier.Sync();
@@ -881,8 +886,8 @@ struct KernelCore::Impl {
std::unique_ptr<KMemoryLayout> memory_layout;
// Threads used for services
- std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
- std::weak_ptr<ServiceThread> default_service_thread;
+ std::unordered_map<ServiceThread*, std::unique_ptr<ServiceThread>> service_threads;
+ ServiceThread* default_service_thread{};
Common::ThreadWorker service_threads_manager;
Common::Barrier service_thread_barrier;
@@ -1122,8 +1127,12 @@ void KernelCore::RegisterCoreThread(std::size_t core_id) {
impl->RegisterCoreThread(core_id);
}
-void KernelCore::RegisterHostThread() {
- impl->RegisterHostThread();
+void KernelCore::RegisterHostThread(KThread* existing_thread) {
+ impl->RegisterHostThread(existing_thread);
+
+ if (existing_thread != nullptr) {
+ ASSERT(GetCurrentEmuThread() == existing_thread);
+ }
}
u32 KernelCore::GetCurrentHostThreadID() const {
@@ -1198,16 +1207,28 @@ void KernelCore::Suspend(bool suspended) {
const bool should_suspend{exception_exited || suspended};
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
- for (auto* process : GetProcessList()) {
- process->SetActivity(activity);
+ std::vector<KScopedAutoObject<KThread>> process_threads;
+ {
+ KScopedSchedulerLock sl{*this};
+
+ if (auto* process = CurrentProcess(); process != nullptr) {
+ process->SetActivity(activity);
+
+ if (!should_suspend) {
+ // Runnable now; no need to wait.
+ return;
+ }
- if (should_suspend) {
- // Wait for execution to stop
for (auto* thread : process->GetThreadList()) {
- thread->WaitUntilSuspended();
+ process_threads.emplace_back(thread);
}
}
}
+
+ // Wait for execution to stop.
+ for (auto& thread : process_threads) {
+ thread->WaitUntilSuspended();
+ }
}
void KernelCore::ShutdownCores() {
@@ -1239,15 +1260,15 @@ void KernelCore::ExitSVCProfile() {
MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[CurrentPhysicalCoreIndex()]);
}
-std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) {
+Kernel::ServiceThread& KernelCore::CreateServiceThread(const std::string& name) {
return impl->CreateServiceThread(*this, name);
}
-std::weak_ptr<Kernel::ServiceThread> KernelCore::GetDefaultServiceThread() const {
- return impl->default_service_thread;
+Kernel::ServiceThread& KernelCore::GetDefaultServiceThread() const {
+ return *impl->default_service_thread;
}
-void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) {
+void KernelCore::ReleaseServiceThread(Kernel::ServiceThread& service_thread) {
impl->ReleaseServiceThread(service_thread);
}