diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 49 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/service_thread.cpp | 24 |
5 files changed, 56 insertions, 25 deletions
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index cc88d08f0..78076a346 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -263,9 +263,9 @@ Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_ | |||
| 263 | R_SUCCEED(); | 263 | R_SUCCEED(); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | Result KThread::InitializeDummyThread(KThread* thread) { | 266 | Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) { |
| 267 | // Initialize the thread. | 267 | // Initialize the thread. |
| 268 | R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy)); | 268 | R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); |
| 269 | 269 | ||
| 270 | // Initialize emulation parameters. | 270 | // Initialize emulation parameters. |
| 271 | thread->stack_parameters.disable_count = 0; | 271 | thread->stack_parameters.disable_count = 0; |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 30aa10c9a..f38c92bff 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -415,7 +415,7 @@ public: | |||
| 415 | 415 | ||
| 416 | static void PostDestroy(uintptr_t arg); | 416 | static void PostDestroy(uintptr_t arg); |
| 417 | 417 | ||
| 418 | [[nodiscard]] static Result InitializeDummyThread(KThread* thread); | 418 | [[nodiscard]] static Result InitializeDummyThread(KThread* thread, KProcess* owner); |
| 419 | 419 | ||
| 420 | [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread, | 420 | [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread, |
| 421 | s32 virt_core); | 421 | s32 virt_core); |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index abff14079..7f800d860 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -91,7 +91,7 @@ struct KernelCore::Impl { | |||
| 91 | pt_heap_region.GetSize()); | 91 | pt_heap_region.GetSize()); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | RegisterHostThread(); | 94 | RegisterHostThread(nullptr); |
| 95 | 95 | ||
| 96 | default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); | 96 | default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); |
| 97 | } | 97 | } |
| @@ -373,15 +373,18 @@ struct KernelCore::Impl { | |||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time | 375 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time |
| 376 | KThread* GetHostDummyThread() { | 376 | KThread* GetHostDummyThread(KThread* existing_thread) { |
| 377 | auto initialize = [this](KThread* thread) { | 377 | auto initialize = [this](KThread* thread) { |
| 378 | ASSERT(KThread::InitializeDummyThread(thread).IsSuccess()); | 378 | ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); |
| 379 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); | 379 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); |
| 380 | return thread; | 380 | return thread; |
| 381 | }; | 381 | }; |
| 382 | 382 | ||
| 383 | thread_local auto raw_thread = KThread(system.Kernel()); | 383 | thread_local KThread raw_thread{system.Kernel()}; |
| 384 | thread_local auto thread = initialize(&raw_thread); | 384 | thread_local KThread* thread = nullptr; |
| 385 | if (thread == nullptr) { | ||
| 386 | thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread; | ||
| 387 | } | ||
| 385 | 388 | ||
| 386 | return thread; | 389 | return thread; |
| 387 | } | 390 | } |
| @@ -396,9 +399,9 @@ struct KernelCore::Impl { | |||
| 396 | } | 399 | } |
| 397 | 400 | ||
| 398 | /// Registers a new host thread by allocating a host thread ID for it | 401 | /// Registers a new host thread by allocating a host thread ID for it |
| 399 | void RegisterHostThread() { | 402 | void RegisterHostThread(KThread* existing_thread) { |
| 400 | [[maybe_unused]] const auto this_id = GetHostThreadId(); | 403 | [[maybe_unused]] const auto this_id = GetHostThreadId(); |
| 401 | [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(); | 404 | [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread); |
| 402 | } | 405 | } |
| 403 | 406 | ||
| 404 | [[nodiscard]] u32 GetCurrentHostThreadID() { | 407 | [[nodiscard]] u32 GetCurrentHostThreadID() { |
| @@ -429,7 +432,7 @@ struct KernelCore::Impl { | |||
| 429 | KThread* GetCurrentEmuThread() { | 432 | KThread* GetCurrentEmuThread() { |
| 430 | const auto thread_id = GetCurrentHostThreadID(); | 433 | const auto thread_id = GetCurrentHostThreadID(); |
| 431 | if (thread_id >= Core::Hardware::NUM_CPU_CORES) { | 434 | if (thread_id >= Core::Hardware::NUM_CPU_CORES) { |
| 432 | return GetHostDummyThread(); | 435 | return GetHostDummyThread(nullptr); |
| 433 | } | 436 | } |
| 434 | 437 | ||
| 435 | return current_thread; | 438 | return current_thread; |
| @@ -1120,8 +1123,12 @@ void KernelCore::RegisterCoreThread(std::size_t core_id) { | |||
| 1120 | impl->RegisterCoreThread(core_id); | 1123 | impl->RegisterCoreThread(core_id); |
| 1121 | } | 1124 | } |
| 1122 | 1125 | ||
| 1123 | void KernelCore::RegisterHostThread() { | 1126 | void KernelCore::RegisterHostThread(KThread* existing_thread) { |
| 1124 | impl->RegisterHostThread(); | 1127 | impl->RegisterHostThread(existing_thread); |
| 1128 | |||
| 1129 | if (existing_thread != nullptr) { | ||
| 1130 | ASSERT(GetCurrentEmuThread() == existing_thread); | ||
| 1131 | } | ||
| 1125 | } | 1132 | } |
| 1126 | 1133 | ||
| 1127 | u32 KernelCore::GetCurrentHostThreadID() const { | 1134 | u32 KernelCore::GetCurrentHostThreadID() const { |
| @@ -1196,16 +1203,28 @@ void KernelCore::Suspend(bool suspended) { | |||
| 1196 | const bool should_suspend{exception_exited || suspended}; | 1203 | const bool should_suspend{exception_exited || suspended}; |
| 1197 | const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; | 1204 | const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; |
| 1198 | 1205 | ||
| 1199 | for (auto* process : GetProcessList()) { | 1206 | std::vector<KScopedAutoObject<KThread>> process_threads; |
| 1200 | process->SetActivity(activity); | 1207 | { |
| 1208 | KScopedSchedulerLock sl{*this}; | ||
| 1209 | |||
| 1210 | if (auto* process = CurrentProcess(); process != nullptr) { | ||
| 1211 | process->SetActivity(activity); | ||
| 1212 | |||
| 1213 | if (!should_suspend) { | ||
| 1214 | // Runnable now; no need to wait. | ||
| 1215 | return; | ||
| 1216 | } | ||
| 1201 | 1217 | ||
| 1202 | if (should_suspend) { | ||
| 1203 | // Wait for execution to stop | ||
| 1204 | for (auto* thread : process->GetThreadList()) { | 1218 | for (auto* thread : process->GetThreadList()) { |
| 1205 | thread->WaitUntilSuspended(); | 1219 | process_threads.emplace_back(thread); |
| 1206 | } | 1220 | } |
| 1207 | } | 1221 | } |
| 1208 | } | 1222 | } |
| 1223 | |||
| 1224 | // Wait for execution to stop. | ||
| 1225 | for (auto& thread : process_threads) { | ||
| 1226 | thread->WaitUntilSuspended(); | ||
| 1227 | } | ||
| 1209 | } | 1228 | } |
| 1210 | 1229 | ||
| 1211 | void KernelCore::ShutdownCores() { | 1230 | void KernelCore::ShutdownCores() { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 29617d736..2e22fe0f6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -240,7 +240,7 @@ public: | |||
| 240 | void RegisterCoreThread(std::size_t core_id); | 240 | void RegisterCoreThread(std::size_t core_id); |
| 241 | 241 | ||
| 242 | /// Register the current thread as a non CPU core thread. | 242 | /// Register the current thread as a non CPU core thread. |
| 243 | void RegisterHostThread(); | 243 | void RegisterHostThread(KThread* existing_thread = nullptr); |
| 244 | 244 | ||
| 245 | /// Gets the virtual memory manager for the kernel. | 245 | /// Gets the virtual memory manager for the kernel. |
| 246 | KMemoryManager& MemoryManager(); | 246 | KMemoryManager& MemoryManager(); |
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index c8fe42537..7a85be77f 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -36,11 +36,12 @@ public: | |||
| 36 | private: | 36 | private: |
| 37 | KernelCore& kernel; | 37 | KernelCore& kernel; |
| 38 | 38 | ||
| 39 | std::jthread m_thread; | 39 | std::jthread m_host_thread; |
| 40 | std::mutex m_session_mutex; | 40 | std::mutex m_session_mutex; |
| 41 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; | 41 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; |
| 42 | KEvent* m_wakeup_event; | 42 | KEvent* m_wakeup_event; |
| 43 | KProcess* m_process; | 43 | KProcess* m_process; |
| 44 | KThread* m_thread; | ||
| 44 | std::atomic<bool> m_shutdown_requested; | 45 | std::atomic<bool> m_shutdown_requested; |
| 45 | const std::string m_service_name; | 46 | const std::string m_service_name; |
| 46 | }; | 47 | }; |
| @@ -132,7 +133,7 @@ void ServiceThread::Impl::SessionClosed(KServerSession* server_session, | |||
| 132 | void ServiceThread::Impl::LoopProcess() { | 133 | void ServiceThread::Impl::LoopProcess() { |
| 133 | Common::SetCurrentThreadName(m_service_name.c_str()); | 134 | Common::SetCurrentThreadName(m_service_name.c_str()); |
| 134 | 135 | ||
| 135 | kernel.RegisterHostThread(); | 136 | kernel.RegisterHostThread(m_thread); |
| 136 | 137 | ||
| 137 | while (!m_shutdown_requested.load()) { | 138 | while (!m_shutdown_requested.load()) { |
| 138 | WaitAndProcessImpl(); | 139 | WaitAndProcessImpl(); |
| @@ -160,7 +161,7 @@ ServiceThread::Impl::~Impl() { | |||
| 160 | // Shut down the processing thread. | 161 | // Shut down the processing thread. |
| 161 | m_shutdown_requested.store(true); | 162 | m_shutdown_requested.store(true); |
| 162 | m_wakeup_event->Signal(); | 163 | m_wakeup_event->Signal(); |
| 163 | m_thread.join(); | 164 | m_host_thread.join(); |
| 164 | 165 | ||
| 165 | // Lock mutex. | 166 | // Lock mutex. |
| 166 | m_session_mutex.lock(); | 167 | m_session_mutex.lock(); |
| @@ -177,6 +178,9 @@ ServiceThread::Impl::~Impl() { | |||
| 177 | m_wakeup_event->GetReadableEvent().Close(); | 178 | m_wakeup_event->GetReadableEvent().Close(); |
| 178 | m_wakeup_event->Close(); | 179 | m_wakeup_event->Close(); |
| 179 | 180 | ||
| 181 | // Close thread. | ||
| 182 | m_thread->Close(); | ||
| 183 | |||
| 180 | // Close process. | 184 | // Close process. |
| 181 | m_process->Close(); | 185 | m_process->Close(); |
| 182 | } | 186 | } |
| @@ -199,11 +203,19 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | |||
| 199 | // Commit the event reservation. | 203 | // Commit the event reservation. |
| 200 | event_reservation.Commit(); | 204 | event_reservation.Commit(); |
| 201 | 205 | ||
| 202 | // Register the event. | 206 | // Reserve a new thread from the process resource limit |
| 203 | KEvent::Register(kernel, m_wakeup_event); | 207 | KScopedResourceReservation thread_reservation(m_process, LimitableResource::Threads); |
| 208 | ASSERT(thread_reservation.Succeeded()); | ||
| 209 | |||
| 210 | // Initialize thread. | ||
| 211 | m_thread = KThread::Create(kernel); | ||
| 212 | ASSERT(KThread::InitializeDummyThread(m_thread, m_process).IsSuccess()); | ||
| 213 | |||
| 214 | // Commit the thread reservation. | ||
| 215 | thread_reservation.Commit(); | ||
| 204 | 216 | ||
| 205 | // Start thread. | 217 | // Start thread. |
| 206 | m_thread = std::jthread([this] { LoopProcess(); }); | 218 | m_host_thread = std::jthread([this] { LoopProcess(); }); |
| 207 | } | 219 | } |
| 208 | 220 | ||
| 209 | ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) | 221 | ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) |