diff options
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 109 |
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); } |