diff options
| author | 2021-11-09 20:54:44 -0800 | |
|---|---|---|
| committer | 2021-12-06 16:39:17 -0800 | |
| commit | 5dff28290fc4fc9bc3db3c32476dd93b2c4414c6 (patch) | |
| tree | 45bccef430ad51ccef88b66036f511d8f52964d0 /src | |
| parent | hle: kernel: KLightLock: Migrate to updated KThreadQueue. (diff) | |
| download | yuzu-5dff28290fc4fc9bc3db3c32476dd93b2c4414c6.tar.gz yuzu-5dff28290fc4fc9bc3db3c32476dd93b2c4414c6.tar.xz yuzu-5dff28290fc4fc9bc3db3c32476dd93b2c4414c6.zip | |
hle: kernel: KLightConditionVariable: Migrate to updated KThreadQueue.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.cpp | 80 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.h | 60 |
3 files changed, 87 insertions, 54 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c42a29cc7..cd99b447b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -185,6 +185,7 @@ add_library(core STATIC | |||
| 185 | hle/kernel/k_event.h | 185 | hle/kernel/k_event.h |
| 186 | hle/kernel/k_handle_table.cpp | 186 | hle/kernel/k_handle_table.cpp |
| 187 | hle/kernel/k_handle_table.h | 187 | hle/kernel/k_handle_table.h |
| 188 | hle/kernel/k_light_condition_variable.cpp | ||
| 188 | hle/kernel/k_light_condition_variable.h | 189 | hle/kernel/k_light_condition_variable.h |
| 189 | hle/kernel/k_light_lock.cpp | 190 | hle/kernel/k_light_lock.cpp |
| 190 | hle/kernel/k_light_lock.h | 191 | hle/kernel/k_light_lock.h |
diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp new file mode 100644 index 000000000..9ff710084 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.cpp | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/k_light_condition_variable.h" | ||
| 6 | #include "core/hle/kernel/k_scheduler.h" | ||
| 7 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | ||
| 8 | #include "core/hle/kernel/k_thread_queue.h" | ||
| 9 | #include "core/hle/kernel/svc_results.h" | ||
| 10 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | |||
| 15 | class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { | ||
| 16 | private: | ||
| 17 | KThread::WaiterList* m_wait_list; | ||
| 18 | bool m_allow_terminating_thread; | ||
| 19 | |||
| 20 | public: | ||
| 21 | ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl, | ||
| 22 | bool term) | ||
| 23 | : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} | ||
| 24 | |||
| 25 | virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, | ||
| 26 | bool cancel_timer_task) override { | ||
| 27 | // Only process waits if we're allowed to. | ||
| 28 | if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { | ||
| 29 | return; | ||
| 30 | } | ||
| 31 | |||
| 32 | // Remove the thread from the waiting thread from the light condition variable. | ||
| 33 | m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); | ||
| 34 | |||
| 35 | // Invoke the base cancel wait handler. | ||
| 36 | KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); | ||
| 37 | } | ||
| 38 | }; | ||
| 39 | |||
| 40 | } // namespace | ||
| 41 | |||
| 42 | void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { | ||
| 43 | // Create thread queue. | ||
| 44 | KThread* owner = GetCurrentThreadPointer(kernel); | ||
| 45 | |||
| 46 | ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), | ||
| 47 | allow_terminating_thread); | ||
| 48 | |||
| 49 | // Sleep the thread. | ||
| 50 | { | ||
| 51 | KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); | ||
| 52 | |||
| 53 | if (!allow_terminating_thread && owner->IsTerminationRequested()) { | ||
| 54 | lk.CancelSleep(); | ||
| 55 | return; | ||
| 56 | } | ||
| 57 | |||
| 58 | lock->Unlock(); | ||
| 59 | |||
| 60 | // Add the thread to the queue. | ||
| 61 | wait_list.push_back(*owner); | ||
| 62 | |||
| 63 | // Begin waiting. | ||
| 64 | owner->BeginWait(std::addressof(wait_queue)); | ||
| 65 | } | ||
| 66 | |||
| 67 | // Re-acquire the lock. | ||
| 68 | lock->Lock(); | ||
| 69 | } | ||
| 70 | |||
| 71 | void KLightConditionVariable::Broadcast() { | ||
| 72 | KScopedSchedulerLock lk(kernel); | ||
| 73 | |||
| 74 | // Signal all threads. | ||
| 75 | for (auto it = wait_list.begin(); it != wait_list.end(); it = wait_list.erase(it)) { | ||
| 76 | it->EndWait(ResultSuccess); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index fb0ad783a..65d3bc3e1 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h | |||
| @@ -1,73 +1,25 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | 1 | // Copyright 2021 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | 5 | #pragma once |
| 9 | 6 | ||
| 10 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 11 | #include "core/hle/kernel/k_scheduler.h" | 8 | #include "core/hle/kernel/k_thread.h" |
| 12 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | ||
| 13 | #include "core/hle/kernel/time_manager.h" | ||
| 14 | 9 | ||
| 15 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | |||
| 16 | class KernelCore; | 12 | class KernelCore; |
| 13 | class KLightLock; | ||
| 17 | 14 | ||
| 18 | class KLightConditionVariable { | 15 | class KLightConditionVariable { |
| 19 | public: | 16 | public: |
| 20 | explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} | 17 | explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} |
| 21 | 18 | ||
| 22 | void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) { | 19 | void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true); |
| 23 | WaitImpl(lock, timeout, allow_terminating_thread); | 20 | void Broadcast(); |
| 24 | } | ||
| 25 | |||
| 26 | void Broadcast() { | ||
| 27 | KScopedSchedulerLock lk{kernel}; | ||
| 28 | |||
| 29 | // Signal all threads. | ||
| 30 | for (auto& thread : wait_list) { | ||
| 31 | thread.SetState(ThreadState::Runnable); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | 21 | ||
| 35 | private: | 22 | private: |
| 36 | void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { | ||
| 37 | KThread* owner = GetCurrentThreadPointer(kernel); | ||
| 38 | |||
| 39 | // Sleep the thread. | ||
| 40 | { | ||
| 41 | KScopedSchedulerLockAndSleep lk{kernel, owner, timeout}; | ||
| 42 | |||
| 43 | if (!allow_terminating_thread && owner->IsTerminationRequested()) { | ||
| 44 | lk.CancelSleep(); | ||
| 45 | return; | ||
| 46 | } | ||
| 47 | |||
| 48 | lock->Unlock(); | ||
| 49 | |||
| 50 | // Set the thread as waiting. | ||
| 51 | GetCurrentThread(kernel).SetState(ThreadState::Waiting); | ||
| 52 | |||
| 53 | // Add the thread to the queue. | ||
| 54 | wait_list.push_back(GetCurrentThread(kernel)); | ||
| 55 | } | ||
| 56 | |||
| 57 | // Remove the thread from the wait list. | ||
| 58 | { | ||
| 59 | KScopedSchedulerLock sl{kernel}; | ||
| 60 | |||
| 61 | wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel))); | ||
| 62 | } | ||
| 63 | |||
| 64 | // Cancel the task that the sleep setup. | ||
| 65 | kernel.TimeManager().UnscheduleTimeEvent(owner); | ||
| 66 | |||
| 67 | // Re-acquire the lock. | ||
| 68 | lock->Lock(); | ||
| 69 | } | ||
| 70 | |||
| 71 | KernelCore& kernel; | 23 | KernelCore& kernel; |
| 72 | KThread::WaiterList wait_list{}; | 24 | KThread::WaiterList wait_list{}; |
| 73 | }; | 25 | }; |