summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2021-11-09 21:28:09 -0800
committerGravatar bunnei2021-12-06 16:39:17 -0800
commitbeb55cb90ee5a830240cd34ebf2ac236eeeb8653 (patch)
treeedcb34d82ef414636b59e75920204068e74de859 /src
parenthle: kernel: KServerSession: Migrate to updated KThreadQueue. (diff)
downloadyuzu-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.cpp67
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
61class ThreadQueueImplForKConditionVariableWaitForAddress final : public KThreadQueue {
62public:
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
76class ThreadQueueImplForKConditionVariableWaitConditionVariable final : public KThreadQueue {
77private:
78 KConditionVariable::ThreadTree* m_tree;
79
80public:
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
62KConditionVariable::KConditionVariable(Core::System& system_) 105KConditionVariable::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
104ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) { 146ResultCode 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) {
259ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { 301ResultCode 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 }