diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/fiber.cpp | 5 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 78 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_worker_task.h | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_worker_task_manager.cpp | 42 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_worker_task_manager.h | 33 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 7 |
11 files changed, 181 insertions, 39 deletions
diff --git a/src/common/fiber.cpp b/src/common/fiber.cpp index 62010d762..81b212e4b 100644 --- a/src/common/fiber.cpp +++ b/src/common/fiber.cpp | |||
| @@ -124,7 +124,10 @@ void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) { | |||
| 124 | 124 | ||
| 125 | // "from" might no longer be valid if the thread was killed | 125 | // "from" might no longer be valid if the thread was killed |
| 126 | if (auto from = weak_from.lock()) { | 126 | if (auto from = weak_from.lock()) { |
| 127 | ASSERT(from->impl->previous_fiber != nullptr); | 127 | if (from->impl->previous_fiber == nullptr) { |
| 128 | ASSERT_MSG(false, "previous_fiber is nullptr!"); | ||
| 129 | return; | ||
| 130 | } | ||
| 128 | from->impl->previous_fiber->impl->context = transfer.fctx; | 131 | from->impl->previous_fiber->impl->context = transfer.fctx; |
| 129 | from->impl->previous_fiber->impl->guard.unlock(); | 132 | from->impl->previous_fiber->impl->guard.unlock(); |
| 130 | from->impl->previous_fiber.reset(); | 133 | from->impl->previous_fiber.reset(); |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b1a746727..6e8d11919 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -247,6 +247,9 @@ add_library(core STATIC | |||
| 247 | hle/kernel/k_trace.h | 247 | hle/kernel/k_trace.h |
| 248 | hle/kernel/k_transfer_memory.cpp | 248 | hle/kernel/k_transfer_memory.cpp |
| 249 | hle/kernel/k_transfer_memory.h | 249 | hle/kernel/k_transfer_memory.h |
| 250 | hle/kernel/k_worker_task.h | ||
| 251 | hle/kernel/k_worker_task_manager.cpp | ||
| 252 | hle/kernel/k_worker_task_manager.h | ||
| 250 | hle/kernel/k_writable_event.cpp | 253 | hle/kernel/k_writable_event.cpp |
| 251 | hle/kernel/k_writable_event.h | 254 | hle/kernel/k_writable_event.h |
| 252 | hle/kernel/kernel.cpp | 255 | hle/kernel/kernel.cpp |
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index cca405fed..265ac6fa1 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -149,6 +149,10 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st | |||
| 149 | return ResultSuccess; | 149 | return ResultSuccess; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | void KProcess::DoWorkerTaskImpl() { | ||
| 153 | UNIMPLEMENTED(); | ||
| 154 | } | ||
| 155 | |||
| 152 | KResourceLimit* KProcess::GetResourceLimit() const { | 156 | KResourceLimit* KProcess::GetResourceLimit() const { |
| 153 | return resource_limit; | 157 | return resource_limit; |
| 154 | } | 158 | } |
| @@ -477,7 +481,7 @@ void KProcess::Finalize() { | |||
| 477 | } | 481 | } |
| 478 | 482 | ||
| 479 | // Perform inherited finalization. | 483 | // Perform inherited finalization. |
| 480 | KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject>::Finalize(); | 484 | KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask>::Finalize(); |
| 481 | } | 485 | } |
| 482 | 486 | ||
| 483 | /** | 487 | /** |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index e7c8b5838..c2a672021 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "core/hle/kernel/k_condition_variable.h" | 15 | #include "core/hle/kernel/k_condition_variable.h" |
| 16 | #include "core/hle/kernel/k_handle_table.h" | 16 | #include "core/hle/kernel/k_handle_table.h" |
| 17 | #include "core/hle/kernel/k_synchronization_object.h" | 17 | #include "core/hle/kernel/k_synchronization_object.h" |
| 18 | #include "core/hle/kernel/k_worker_task.h" | ||
| 18 | #include "core/hle/kernel/process_capability.h" | 19 | #include "core/hle/kernel/process_capability.h" |
| 19 | #include "core/hle/kernel/slab_helpers.h" | 20 | #include "core/hle/kernel/slab_helpers.h" |
| 20 | #include "core/hle/result.h" | 21 | #include "core/hle/result.h" |
| @@ -62,8 +63,7 @@ enum class ProcessStatus { | |||
| 62 | DebugBreak, | 63 | DebugBreak, |
| 63 | }; | 64 | }; |
| 64 | 65 | ||
| 65 | class KProcess final | 66 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { |
| 66 | : public KAutoObjectWithSlabHeapAndContainer<KProcess, KSynchronizationObject> { | ||
| 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | 67 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); |
| 68 | 68 | ||
| 69 | public: | 69 | public: |
| @@ -345,6 +345,8 @@ public: | |||
| 345 | 345 | ||
| 346 | bool IsSignaled() const override; | 346 | bool IsSignaled() const override; |
| 347 | 347 | ||
| 348 | void DoWorkerTaskImpl(); | ||
| 349 | |||
| 348 | void PinCurrentThread(s32 core_id); | 350 | void PinCurrentThread(s32 core_id); |
| 349 | void UnpinCurrentThread(s32 core_id); | 351 | void UnpinCurrentThread(s32 core_id); |
| 350 | void UnpinThread(KThread* thread); | 352 | void UnpinThread(KThread* thread); |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 71e029a3f..7a5e6fc08 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include "core/hle/kernel/k_system_control.h" | 30 | #include "core/hle/kernel/k_system_control.h" |
| 31 | #include "core/hle/kernel/k_thread.h" | 31 | #include "core/hle/kernel/k_thread.h" |
| 32 | #include "core/hle/kernel/k_thread_queue.h" | 32 | #include "core/hle/kernel/k_thread_queue.h" |
| 33 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 33 | #include "core/hle/kernel/kernel.h" | 34 | #include "core/hle/kernel/kernel.h" |
| 34 | #include "core/hle/kernel/svc_results.h" | 35 | #include "core/hle/kernel/svc_results.h" |
| 35 | #include "core/hle/kernel/time_manager.h" | 36 | #include "core/hle/kernel/time_manager.h" |
| @@ -332,7 +333,7 @@ void KThread::Finalize() { | |||
| 332 | } | 333 | } |
| 333 | 334 | ||
| 334 | // Perform inherited finalization. | 335 | // Perform inherited finalization. |
| 335 | KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>::Finalize(); | 336 | KSynchronizationObject::Finalize(); |
| 336 | } | 337 | } |
| 337 | 338 | ||
| 338 | bool KThread::IsSignaled() const { | 339 | bool KThread::IsSignaled() const { |
| @@ -376,11 +377,28 @@ void KThread::StartTermination() { | |||
| 376 | 377 | ||
| 377 | // Register terminated dpc flag. | 378 | // Register terminated dpc flag. |
| 378 | RegisterDpc(DpcFlag::Terminated); | 379 | RegisterDpc(DpcFlag::Terminated); |
| 380 | } | ||
| 381 | |||
| 382 | void KThread::FinishTermination() { | ||
| 383 | // Ensure that the thread is not executing on any core. | ||
| 384 | if (parent != nullptr) { | ||
| 385 | for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) { | ||
| 386 | KThread* core_thread{}; | ||
| 387 | do { | ||
| 388 | core_thread = kernel.Scheduler(i).GetCurrentThread(); | ||
| 389 | } while (core_thread == this); | ||
| 390 | } | ||
| 391 | } | ||
| 379 | 392 | ||
| 380 | // Close the thread. | 393 | // Close the thread. |
| 381 | this->Close(); | 394 | this->Close(); |
| 382 | } | 395 | } |
| 383 | 396 | ||
| 397 | void KThread::DoWorkerTaskImpl() { | ||
| 398 | // Finish the termination that was begun by Exit(). | ||
| 399 | this->FinishTermination(); | ||
| 400 | } | ||
| 401 | |||
| 384 | void KThread::Pin(s32 current_core) { | 402 | void KThread::Pin(s32 current_core) { |
| 385 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 403 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 386 | 404 | ||
| @@ -417,12 +435,7 @@ void KThread::Pin(s32 current_core) { | |||
| 417 | static_cast<u32>(ThreadState::SuspendShift))); | 435 | static_cast<u32>(ThreadState::SuspendShift))); |
| 418 | 436 | ||
| 419 | // Update our state. | 437 | // Update our state. |
| 420 | const ThreadState old_state = thread_state; | 438 | UpdateState(); |
| 421 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 422 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 423 | if (thread_state != old_state) { | ||
| 424 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 425 | } | ||
| 426 | } | 439 | } |
| 427 | 440 | ||
| 428 | // TODO(bunnei): Update our SVC access permissions. | 441 | // TODO(bunnei): Update our SVC access permissions. |
| @@ -463,20 +476,13 @@ void KThread::Unpin() { | |||
| 463 | } | 476 | } |
| 464 | 477 | ||
| 465 | // Allow performing thread suspension (if termination hasn't been requested). | 478 | // Allow performing thread suspension (if termination hasn't been requested). |
| 466 | { | 479 | if (!IsTerminationRequested()) { |
| 467 | // Update our allow flags. | 480 | // Update our allow flags. |
| 468 | if (!IsTerminationRequested()) { | 481 | suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) + |
| 469 | suspend_allowed_flags |= (1 << (static_cast<u32>(SuspendType::Thread) + | 482 | static_cast<u32>(ThreadState::SuspendShift))); |
| 470 | static_cast<u32>(ThreadState::SuspendShift))); | ||
| 471 | } | ||
| 472 | 483 | ||
| 473 | // Update our state. | 484 | // Update our state. |
| 474 | const ThreadState old_state = thread_state; | 485 | UpdateState(); |
| 475 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 476 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 477 | if (thread_state != old_state) { | ||
| 478 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 479 | } | ||
| 480 | } | 486 | } |
| 481 | 487 | ||
| 482 | // TODO(bunnei): Update our SVC access permissions. | 488 | // TODO(bunnei): Update our SVC access permissions. |
| @@ -689,12 +695,7 @@ void KThread::Resume(SuspendType type) { | |||
| 689 | ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); | 695 | ~(1u << (static_cast<u32>(ThreadState::SuspendShift) + static_cast<u32>(type))); |
| 690 | 696 | ||
| 691 | // Update our state. | 697 | // Update our state. |
| 692 | const ThreadState old_state = thread_state; | 698 | this->UpdateState(); |
| 693 | thread_state = static_cast<ThreadState>(GetSuspendFlags() | | ||
| 694 | static_cast<u32>(old_state & ThreadState::Mask)); | ||
| 695 | if (thread_state != old_state) { | ||
| 696 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 697 | } | ||
| 698 | } | 699 | } |
| 699 | 700 | ||
| 700 | void KThread::WaitCancel() { | 701 | void KThread::WaitCancel() { |
| @@ -721,19 +722,22 @@ void KThread::TrySuspend() { | |||
| 721 | ASSERT(GetNumKernelWaiters() == 0); | 722 | ASSERT(GetNumKernelWaiters() == 0); |
| 722 | 723 | ||
| 723 | // Perform the suspend. | 724 | // Perform the suspend. |
| 724 | Suspend(); | 725 | this->UpdateState(); |
| 725 | } | 726 | } |
| 726 | 727 | ||
| 727 | void KThread::Suspend() { | 728 | void KThread::UpdateState() { |
| 728 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); | 729 | ASSERT(kernel.GlobalSchedulerContext().IsLocked()); |
| 729 | ASSERT(IsSuspendRequested()); | ||
| 730 | 730 | ||
| 731 | // Set our suspend flags in state. | 731 | // Set our suspend flags in state. |
| 732 | const auto old_state = thread_state; | 732 | const auto old_state = thread_state; |
| 733 | thread_state = static_cast<ThreadState>(GetSuspendFlags()) | (old_state & ThreadState::Mask); | 733 | const auto new_state = |
| 734 | static_cast<ThreadState>(this->GetSuspendFlags()) | (old_state & ThreadState::Mask); | ||
| 735 | thread_state = new_state; | ||
| 734 | 736 | ||
| 735 | // Note the state change in scheduler. | 737 | // Note the state change in scheduler. |
| 736 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | 738 | if (new_state != old_state) { |
| 739 | KScheduler::OnThreadStateChanged(kernel, this, old_state); | ||
| 740 | } | ||
| 737 | } | 741 | } |
| 738 | 742 | ||
| 739 | void KThread::Continue() { | 743 | void KThread::Continue() { |
| @@ -998,13 +1002,16 @@ ResultCode KThread::Run() { | |||
| 998 | 1002 | ||
| 999 | // If the current thread has been asked to suspend, suspend it and retry. | 1003 | // If the current thread has been asked to suspend, suspend it and retry. |
| 1000 | if (GetCurrentThread(kernel).IsSuspended()) { | 1004 | if (GetCurrentThread(kernel).IsSuspended()) { |
| 1001 | GetCurrentThread(kernel).Suspend(); | 1005 | GetCurrentThread(kernel).UpdateState(); |
| 1002 | continue; | 1006 | continue; |
| 1003 | } | 1007 | } |
| 1004 | 1008 | ||
| 1005 | // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. | 1009 | // If we're not a kernel thread and we've been asked to suspend, suspend ourselves. |
| 1006 | if (IsUserThread() && IsSuspended()) { | 1010 | if (KProcess* owner = this->GetOwnerProcess(); owner != nullptr) { |
| 1007 | Suspend(); | 1011 | if (IsUserThread() && IsSuspended()) { |
| 1012 | this->UpdateState(); | ||
| 1013 | } | ||
| 1014 | owner->IncrementThreadCount(); | ||
| 1008 | } | 1015 | } |
| 1009 | 1016 | ||
| 1010 | // Set our state and finish. | 1017 | // Set our state and finish. |
| @@ -1031,9 +1038,16 @@ void KThread::Exit() { | |||
| 1031 | 1038 | ||
| 1032 | // Disallow all suspension. | 1039 | // Disallow all suspension. |
| 1033 | suspend_allowed_flags = 0; | 1040 | suspend_allowed_flags = 0; |
| 1041 | this->UpdateState(); | ||
| 1042 | |||
| 1043 | // Disallow all suspension. | ||
| 1044 | suspend_allowed_flags = 0; | ||
| 1034 | 1045 | ||
| 1035 | // Start termination. | 1046 | // Start termination. |
| 1036 | StartTermination(); | 1047 | StartTermination(); |
| 1048 | |||
| 1049 | // Register the thread as a work task. | ||
| 1050 | KWorkerTaskManager::AddTask(kernel, KWorkerTaskManager::WorkerType::Exit, this); | ||
| 1037 | } | 1051 | } |
| 1038 | } | 1052 | } |
| 1039 | 1053 | ||
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 83dfde69b..cc427f6cf 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "core/hle/kernel/k_light_lock.h" | 19 | #include "core/hle/kernel/k_light_lock.h" |
| 20 | #include "core/hle/kernel/k_spin_lock.h" | 20 | #include "core/hle/kernel/k_spin_lock.h" |
| 21 | #include "core/hle/kernel/k_synchronization_object.h" | 21 | #include "core/hle/kernel/k_synchronization_object.h" |
| 22 | #include "core/hle/kernel/k_worker_task.h" | ||
| 22 | #include "core/hle/kernel/slab_helpers.h" | 23 | #include "core/hle/kernel/slab_helpers.h" |
| 23 | #include "core/hle/kernel/svc_common.h" | 24 | #include "core/hle/kernel/svc_common.h" |
| 24 | #include "core/hle/kernel/svc_types.h" | 25 | #include "core/hle/kernel/svc_types.h" |
| @@ -100,7 +101,7 @@ enum class ThreadWaitReasonForDebugging : u32 { | |||
| 100 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); | 101 | [[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel); |
| 101 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); | 102 | [[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); |
| 102 | 103 | ||
| 103 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KSynchronizationObject>, | 104 | class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>, |
| 104 | public boost::intrusive::list_base_hook<> { | 105 | public boost::intrusive::list_base_hook<> { |
| 105 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); | 106 | KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); |
| 106 | 107 | ||
| @@ -192,9 +193,9 @@ public: | |||
| 192 | 193 | ||
| 193 | void TrySuspend(); | 194 | void TrySuspend(); |
| 194 | 195 | ||
| 195 | void Continue(); | 196 | void UpdateState(); |
| 196 | 197 | ||
| 197 | void Suspend(); | 198 | void Continue(); |
| 198 | 199 | ||
| 199 | constexpr void SetSyncedIndex(s32 index) { | 200 | constexpr void SetSyncedIndex(s32 index) { |
| 200 | synced_index = index; | 201 | synced_index = index; |
| @@ -385,6 +386,8 @@ public: | |||
| 385 | 386 | ||
| 386 | void OnTimer(); | 387 | void OnTimer(); |
| 387 | 388 | ||
| 389 | void DoWorkerTaskImpl(); | ||
| 390 | |||
| 388 | static void PostDestroy(uintptr_t arg); | 391 | static void PostDestroy(uintptr_t arg); |
| 389 | 392 | ||
| 390 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); | 393 | [[nodiscard]] static ResultCode InitializeDummyThread(KThread* thread); |
| @@ -679,6 +682,8 @@ private: | |||
| 679 | 682 | ||
| 680 | void StartTermination(); | 683 | void StartTermination(); |
| 681 | 684 | ||
| 685 | void FinishTermination(); | ||
| 686 | |||
| 682 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, | 687 | [[nodiscard]] ResultCode Initialize(KThreadFunction func, uintptr_t arg, VAddr user_stack_top, |
| 683 | s32 prio, s32 virt_core, KProcess* owner, ThreadType type); | 688 | s32 prio, s32 virt_core, KProcess* owner, ThreadType type); |
| 684 | 689 | ||
diff --git a/src/core/hle/kernel/k_worker_task.h b/src/core/hle/kernel/k_worker_task.h new file mode 100644 index 000000000..b7794c6a8 --- /dev/null +++ b/src/core/hle/kernel/k_worker_task.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/kernel/k_synchronization_object.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | |||
| 11 | class KWorkerTask : public KSynchronizationObject { | ||
| 12 | public: | ||
| 13 | explicit KWorkerTask(KernelCore& kernel_); | ||
| 14 | |||
| 15 | void DoWorkerTask(); | ||
| 16 | }; | ||
| 17 | |||
| 18 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_worker_task_manager.cpp b/src/core/hle/kernel/k_worker_task_manager.cpp new file mode 100644 index 000000000..785e08111 --- /dev/null +++ b/src/core/hle/kernel/k_worker_task_manager.cpp | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/assert.h" | ||
| 6 | #include "core/hle/kernel/k_process.h" | ||
| 7 | #include "core/hle/kernel/k_thread.h" | ||
| 8 | #include "core/hle/kernel/k_worker_task.h" | ||
| 9 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | KWorkerTask::KWorkerTask(KernelCore& kernel_) : KSynchronizationObject{kernel_} {} | ||
| 15 | |||
| 16 | void KWorkerTask::DoWorkerTask() { | ||
| 17 | if (auto* const thread = this->DynamicCast<KThread*>(); thread != nullptr) { | ||
| 18 | return thread->DoWorkerTaskImpl(); | ||
| 19 | } else { | ||
| 20 | auto* const process = this->DynamicCast<KProcess*>(); | ||
| 21 | ASSERT(process != nullptr); | ||
| 22 | |||
| 23 | return process->DoWorkerTaskImpl(); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | KWorkerTaskManager::KWorkerTaskManager() : m_waiting_thread(1, "yuzu:KWorkerTaskManager") {} | ||
| 28 | |||
| 29 | void KWorkerTaskManager::AddTask(KernelCore& kernel, WorkerType type, KWorkerTask* task) { | ||
| 30 | ASSERT(type <= WorkerType::Count); | ||
| 31 | kernel.WorkerTaskManager().AddTask(kernel, task); | ||
| 32 | } | ||
| 33 | |||
| 34 | void KWorkerTaskManager::AddTask(KernelCore& kernel, KWorkerTask* task) { | ||
| 35 | KScopedSchedulerLock sl(kernel); | ||
| 36 | m_waiting_thread.QueueWork([task]() { | ||
| 37 | // Do the task. | ||
| 38 | task->DoWorkerTask(); | ||
| 39 | }); | ||
| 40 | } | ||
| 41 | |||
| 42 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_worker_task_manager.h b/src/core/hle/kernel/k_worker_task_manager.h new file mode 100644 index 000000000..43d1bfcec --- /dev/null +++ b/src/core/hle/kernel/k_worker_task_manager.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | // Copyright 2022 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | #include "common/thread_worker.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | class KernelCore; | ||
| 13 | class KWorkerTask; | ||
| 14 | |||
| 15 | class KWorkerTaskManager final { | ||
| 16 | public: | ||
| 17 | enum class WorkerType : u32 { | ||
| 18 | Exit, | ||
| 19 | Count, | ||
| 20 | }; | ||
| 21 | |||
| 22 | KWorkerTaskManager(); | ||
| 23 | |||
| 24 | static void AddTask(KernelCore& kernel_, WorkerType type, KWorkerTask* task); | ||
| 25 | |||
| 26 | private: | ||
| 27 | void AddTask(KernelCore& kernel, KWorkerTask* task); | ||
| 28 | |||
| 29 | private: | ||
| 30 | Common::ThreadWorker m_waiting_thread; | ||
| 31 | }; | ||
| 32 | |||
| 33 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0b618fb46..e5cf9abb3 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include "core/hle/kernel/k_shared_memory.h" | 37 | #include "core/hle/kernel/k_shared_memory.h" |
| 38 | #include "core/hle/kernel/k_slab_heap.h" | 38 | #include "core/hle/kernel/k_slab_heap.h" |
| 39 | #include "core/hle/kernel/k_thread.h" | 39 | #include "core/hle/kernel/k_thread.h" |
| 40 | #include "core/hle/kernel/k_worker_task_manager.h" | ||
| 40 | #include "core/hle/kernel/kernel.h" | 41 | #include "core/hle/kernel/kernel.h" |
| 41 | #include "core/hle/kernel/physical_core.h" | 42 | #include "core/hle/kernel/physical_core.h" |
| 42 | #include "core/hle/kernel/service_thread.h" | 43 | #include "core/hle/kernel/service_thread.h" |
| @@ -797,6 +798,8 @@ struct KernelCore::Impl { | |||
| 797 | 798 | ||
| 798 | std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; | 799 | std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; |
| 799 | 800 | ||
| 801 | KWorkerTaskManager worker_task_manager; | ||
| 802 | |||
| 800 | // System context | 803 | // System context |
| 801 | Core::System& system; | 804 | Core::System& system; |
| 802 | }; | 805 | }; |
| @@ -1137,6 +1140,14 @@ const Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() const { | |||
| 1137 | return impl->slab_resource_counts; | 1140 | return impl->slab_resource_counts; |
| 1138 | } | 1141 | } |
| 1139 | 1142 | ||
| 1143 | KWorkerTaskManager& KernelCore::WorkerTaskManager() { | ||
| 1144 | return impl->worker_task_manager; | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | const KWorkerTaskManager& KernelCore::WorkerTaskManager() const { | ||
| 1148 | return impl->worker_task_manager; | ||
| 1149 | } | ||
| 1150 | |||
| 1140 | bool KernelCore::IsPhantomModeForSingleCore() const { | 1151 | bool KernelCore::IsPhantomModeForSingleCore() const { |
| 1141 | return impl->IsPhantomModeForSingleCore(); | 1152 | return impl->IsPhantomModeForSingleCore(); |
| 1142 | } | 1153 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index b9b423908..0e04fc3bb 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -52,6 +52,7 @@ class KSharedMemory; | |||
| 52 | class KSharedMemoryInfo; | 52 | class KSharedMemoryInfo; |
| 53 | class KThread; | 53 | class KThread; |
| 54 | class KTransferMemory; | 54 | class KTransferMemory; |
| 55 | class KWorkerTaskManager; | ||
| 55 | class KWritableEvent; | 56 | class KWritableEvent; |
| 56 | class KCodeMemory; | 57 | class KCodeMemory; |
| 57 | class PhysicalCore; | 58 | class PhysicalCore; |
| @@ -343,6 +344,12 @@ public: | |||
| 343 | /// Gets the current slab resource counts. | 344 | /// Gets the current slab resource counts. |
| 344 | const Init::KSlabResourceCounts& SlabResourceCounts() const; | 345 | const Init::KSlabResourceCounts& SlabResourceCounts() const; |
| 345 | 346 | ||
| 347 | /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks. | ||
| 348 | KWorkerTaskManager& WorkerTaskManager(); | ||
| 349 | |||
| 350 | /// Gets the current worker task manager, used for dispatching KThread/KProcess tasks. | ||
| 351 | const KWorkerTaskManager& WorkerTaskManager() const; | ||
| 352 | |||
| 346 | private: | 353 | private: |
| 347 | friend class KProcess; | 354 | friend class KProcess; |
| 348 | friend class KThread; | 355 | friend class KThread; |