diff options
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread_queue.h | 81 |
2 files changed, 82 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 88a31e0f2..843bce150 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -170,6 +170,7 @@ add_library(core STATIC hle/kernel/k_synchronization_object.h hle/kernel/k_thread.cpp hle/kernel/k_thread.h + hle/kernel/k_thread_queue.h hle/kernel/kernel.cpp hle/kernel/kernel.h hle/kernel/memory/address_space_info.cpp diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h new file mode 100644 index 000000000..c52eba249 --- /dev/null +++ b/src/core/hle/kernel/k_thread_queue.h @@ -0,0 +1,81 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/k_thread.h" + +namespace Kernel { + +class KThreadQueue { +public: + explicit KThreadQueue(KernelCore& kernel) : kernel{kernel} {} + + bool IsEmpty() const { + return wait_list.empty(); + } + + KThread::WaiterList::iterator begin() { + return wait_list.begin(); + } + KThread::WaiterList::iterator end() { + return wait_list.end(); + } + + bool SleepThread(KThread* t) { + KScopedSchedulerLock sl{kernel}; + + // If the thread needs terminating, don't enqueue it. + if (t->IsTerminationRequested()) { + return false; + } + + // Set the thread's queue and mark it as waiting. + t->SetSleepingQueue(this); + t->SetState(ThreadState::Waiting); + + // Add the thread to the queue. + wait_list.push_back(*t); + + return true; + } + + void WakeupThread(KThread* t) { + KScopedSchedulerLock sl{kernel}; + + // Remove the thread from the queue. + wait_list.erase(wait_list.iterator_to(*t)); + + // Mark the thread as no longer sleeping. + t->SetState(ThreadState::Runnable); + t->SetSleepingQueue(nullptr); + } + + KThread* WakeupFrontThread() { + KScopedSchedulerLock sl{kernel}; + + if (wait_list.empty()) { + return nullptr; + } else { + // Remove the thread from the queue. + auto it = wait_list.begin(); + KThread* thread = std::addressof(*it); + wait_list.erase(it); + + ASSERT(thread->GetState() == ThreadState::Waiting); + + // Mark the thread as no longer sleeping. + thread->SetState(ThreadState::Runnable); + thread->SetSleepingQueue(nullptr); + + return thread; + } + } + +private: + KernelCore& kernel; + KThread::WaiterList wait_list{}; +}; + +} // namespace Kernel |