diff options
| author | 2021-11-09 21:28:09 -0800 | |
|---|---|---|
| committer | 2021-12-06 16:39:17 -0800 | |
| commit | beb55cb90ee5a830240cd34ebf2ac236eeeb8653 (patch) | |
| tree | edcb34d82ef414636b59e75920204068e74de859 /src | |
| parent | hle: kernel: KServerSession: Migrate to updated KThreadQueue. (diff) | |
| download | yuzu-beb55cb90ee5a830240cd34ebf2ac236eeeb8653.tar.gz yuzu-beb55cb90ee5a830240cd34ebf2ac236eeeb8653.tar.xz yuzu-beb55cb90ee5a830240cd34ebf2ac236eeeb8653.zip | |
hle: kernel: KConditionVariable: Migrate to updated KThreadQueue.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_condition_variable.cpp | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index 9eacbed7e..34c1eae65 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 11 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 12 | #include "core/hle/kernel/k_synchronization_object.h" | 12 | #include "core/hle/kernel/k_synchronization_object.h" |
| 13 | #include "core/hle/kernel/k_thread.h" | 13 | #include "core/hle/kernel/k_thread.h" |
| 14 | #include "core/hle/kernel/k_thread_queue.h" | ||
| 14 | #include "core/hle/kernel/kernel.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 15 | #include "core/hle/kernel/svc_common.h" | 16 | #include "core/hle/kernel/svc_common.h" |
| 16 | #include "core/hle/kernel/svc_results.h" | 17 | #include "core/hle/kernel/svc_results.h" |
| @@ -57,6 +58,48 @@ bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero | |||
| 57 | return true; | 58 | return true; |
| 58 | } | 59 | } |
| 59 | 60 | ||
| 61 | class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue { | ||
| 62 | public: | ||
| 63 | explicit ThreadQueueImplForKConditionVariableWaitForAddress(KernelCore& kernel_) | ||
| 64 | : KThreadQueue(kernel_) {} | ||
| 65 | |||
| 66 | virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, | ||
| 67 | bool cancel_timer_task) override { | ||
| 68 | // Remove the thread as a waiter from its owner. | ||
| 69 | waiting_thread->GetLockOwner()->RemoveWaiter(waiting_thread); | ||
| 70 | |||
| 71 | // Invoke the base cancel wait handler. | ||
| 72 | KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | class ThreadQueueImplForKConditionVariableWaitConditionVariable final : public KThreadQueue { | ||
| 77 | private: | ||
| 78 | KConditionVariable::ThreadTree* m_tree; | ||
| 79 | |||
| 80 | public: | ||
| 81 | explicit ThreadQueueImplForKConditionVariableWaitConditionVariable( | ||
| 82 | KernelCore& kernel_, KConditionVariable::ThreadTree* t) | ||
| 83 | : KThreadQueue(kernel_), m_tree(t) {} | ||
| 84 | |||
| 85 | virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, | ||
| 86 | bool cancel_timer_task) override { | ||
| 87 | // Remove the thread as a waiter from its owner. | ||
| 88 | if (KThread* owner = waiting_thread->GetLockOwner(); owner != nullptr) { | ||
| 89 | owner->RemoveWaiter(waiting_thread); | ||
| 90 | } | ||
| 91 | |||
| 92 | // If the thread is waiting on a condvar, remove it from the tree. | ||
| 93 | if (waiting_thread->IsWaitingForConditionVariable()) { | ||
| 94 | m_tree->erase(m_tree->iterator_to(*waiting_thread)); | ||
| 95 | waiting_thread->ClearConditionVariable(); | ||
| 96 | } | ||
| 97 | |||
| 98 | // Invoke the base cancel wait handler. | ||
| 99 | KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); | ||
| 100 | } | ||
| 101 | }; | ||
| 102 | |||
| 60 | } // namespace | 103 | } // namespace |
| 61 | 104 | ||
| 62 | KConditionVariable::KConditionVariable(Core::System& system_) | 105 | KConditionVariable::KConditionVariable(Core::System& system_) |
| @@ -84,8 +127,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { | |||
| 84 | next_value |= Svc::HandleWaitMask; | 127 | next_value |= Svc::HandleWaitMask; |
| 85 | } | 128 | } |
| 86 | 129 | ||
| 87 | next_owner_thread->SetWaitResult(ResultSuccess); | 130 | next_owner_thread->EndWait(ResultSuccess); |
| 88 | next_owner_thread->Wakeup(); | ||
| 89 | } | 131 | } |
| 90 | 132 | ||
| 91 | // Write the value to userspace. | 133 | // Write the value to userspace. |
| @@ -103,6 +145,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) { | |||
| 103 | 145 | ||
| 104 | ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { | 146 | ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { |
| 105 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); | 147 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 148 | ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel); | ||
| 106 | 149 | ||
| 107 | // Wait for the address. | 150 | // Wait for the address. |
| 108 | { | 151 | { |
| @@ -133,7 +176,9 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val | |||
| 133 | // Update the lock. | 176 | // Update the lock. |
| 134 | cur_thread->SetAddressKey(addr, value); | 177 | cur_thread->SetAddressKey(addr, value); |
| 135 | owner_thread->AddWaiter(cur_thread); | 178 | owner_thread->AddWaiter(cur_thread); |
| 136 | cur_thread->SetState(ThreadState::Waiting); | 179 | |
| 180 | // Begin waiting. | ||
| 181 | cur_thread->BeginWait(std::addressof(wait_queue)); | ||
| 137 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); | 182 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); |
| 138 | cur_thread->SetMutexWaitAddressForDebugging(addr); | 183 | cur_thread->SetMutexWaitAddressForDebugging(addr); |
| 139 | } | 184 | } |
| @@ -178,8 +223,7 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { | |||
| 178 | if (can_access) { | 223 | if (can_access) { |
| 179 | if (prev_tag == Svc::InvalidHandle) { | 224 | if (prev_tag == Svc::InvalidHandle) { |
| 180 | // If nobody held the lock previously, we're all good. | 225 | // If nobody held the lock previously, we're all good. |
| 181 | thread->SetWaitResult(ResultSuccess); | 226 | thread->EndWait(ResultSuccess); |
| 182 | thread->Wakeup(); | ||
| 183 | } else { | 227 | } else { |
| 184 | // Get the previous owner. | 228 | // Get the previous owner. |
| 185 | KThread* owner_thread = kernel.CurrentProcess() | 229 | KThread* owner_thread = kernel.CurrentProcess() |
| @@ -194,14 +238,12 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) { | |||
| 194 | thread_to_close = owner_thread; | 238 | thread_to_close = owner_thread; |
| 195 | } else { | 239 | } else { |
| 196 | // The lock was tagged with a thread that doesn't exist. | 240 | // The lock was tagged with a thread that doesn't exist. |
| 197 | thread->SetWaitResult(ResultInvalidState); | 241 | thread->EndWait(ResultInvalidState); |
| 198 | thread->Wakeup(); | ||
| 199 | } | 242 | } |
| 200 | } | 243 | } |
| 201 | } else { | 244 | } else { |
| 202 | // If the address wasn't accessible, note so. | 245 | // If the address wasn't accessible, note so. |
| 203 | thread->SetWaitResult(ResultInvalidCurrentMemory); | 246 | thread->EndWait(ResultInvalidCurrentMemory); |
| 204 | thread->Wakeup(); | ||
| 205 | } | 247 | } |
| 206 | 248 | ||
| 207 | return thread_to_close; | 249 | return thread_to_close; |
| @@ -259,6 +301,8 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 259 | ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { | 301 | ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { |
| 260 | // Prepare to wait. | 302 | // Prepare to wait. |
| 261 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); | 303 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 304 | ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( | ||
| 305 | kernel, std::addressof(thread_tree)); | ||
| 262 | 306 | ||
| 263 | { | 307 | { |
| 264 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; | 308 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; |
| @@ -289,8 +333,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) | |||
| 289 | } | 333 | } |
| 290 | 334 | ||
| 291 | // Wake up the next owner. | 335 | // Wake up the next owner. |
| 292 | next_owner_thread->SetWaitResult(ResultSuccess); | 336 | next_owner_thread->EndWait(ResultSuccess); |
| 293 | next_owner_thread->Wakeup(); | ||
| 294 | } | 337 | } |
| 295 | 338 | ||
| 296 | // Write to the cv key. | 339 | // Write to the cv key. |
| @@ -315,7 +358,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) | |||
| 315 | 358 | ||
| 316 | // If the timeout is non-zero, set the thread as waiting. | 359 | // If the timeout is non-zero, set the thread as waiting. |
| 317 | if (timeout != 0) { | 360 | if (timeout != 0) { |
| 318 | cur_thread->SetState(ThreadState::Waiting); | 361 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 319 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); | 362 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); |
| 320 | cur_thread->SetMutexWaitAddressForDebugging(addr); | 363 | cur_thread->SetMutexWaitAddressForDebugging(addr); |
| 321 | } | 364 | } |