diff options
| author | 2021-11-09 19:23:37 -0800 | |
|---|---|---|
| committer | 2021-12-06 16:39:17 -0800 | |
| commit | 15c721b90977865d964e26537f8a8f8740134164 (patch) | |
| tree | 7692c08ffb2e208e86091d52f9370f94716d3231 /src/core/hle/kernel | |
| parent | hle: kernel: KThread: Remove tracking of sync object from threads. (diff) | |
| download | yuzu-15c721b90977865d964e26537f8a8f8740134164.tar.gz yuzu-15c721b90977865d964e26537f8a8f8740134164.tar.xz yuzu-15c721b90977865d964e26537f8a8f8740134164.zip | |
hle: kernel: KAddressArbiter: Migrate to updated KThreadQueue.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 82 |
1 files changed, 39 insertions, 43 deletions
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index c5c81a880..165475fbf 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include "core/hle/kernel/k_scheduler.h" | 8 | #include "core/hle/kernel/k_scheduler.h" |
| 9 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" | 9 | #include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" |
| 10 | #include "core/hle/kernel/k_thread.h" | 10 | #include "core/hle/kernel/k_thread.h" |
| 11 | #include "core/hle/kernel/k_thread_queue.h" | ||
| 11 | #include "core/hle/kernel/kernel.h" | 12 | #include "core/hle/kernel/kernel.h" |
| 12 | #include "core/hle/kernel/svc_results.h" | 13 | #include "core/hle/kernel/svc_results.h" |
| 13 | #include "core/hle/kernel/time_manager.h" | 14 | #include "core/hle/kernel/time_manager.h" |
| @@ -85,6 +86,27 @@ bool UpdateIfEqual(Core::System& system, s32* out, VAddr address, s32 value, s32 | |||
| 85 | return true; | 86 | return true; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 89 | class ThreadQueueImplForKAddressArbiter final : public KThreadQueue { | ||
| 90 | private: | ||
| 91 | KAddressArbiter::ThreadTree* m_tree; | ||
| 92 | |||
| 93 | public: | ||
| 94 | explicit ThreadQueueImplForKAddressArbiter(KernelCore& kernel_, KAddressArbiter::ThreadTree* t) | ||
| 95 | : KThreadQueue(kernel_), m_tree(t) {} | ||
| 96 | |||
| 97 | virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, | ||
| 98 | bool cancel_timer_task) override { | ||
| 99 | // If the thread is waiting on an address arbiter, remove it from the tree. | ||
| 100 | if (waiting_thread->IsWaitingForAddressArbiter()) { | ||
| 101 | m_tree->erase(m_tree->iterator_to(*waiting_thread)); | ||
| 102 | waiting_thread->ClearAddressArbiter(); | ||
| 103 | } | ||
| 104 | |||
| 105 | // Invoke the base cancel wait handler. | ||
| 106 | KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); | ||
| 107 | } | ||
| 108 | }; | ||
| 109 | |||
| 88 | } // namespace | 110 | } // namespace |
| 89 | 111 | ||
| 90 | ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { | 112 | ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { |
| @@ -96,14 +118,14 @@ ResultCode KAddressArbiter::Signal(VAddr addr, s32 count) { | |||
| 96 | auto it = thread_tree.nfind_light({addr, -1}); | 118 | auto it = thread_tree.nfind_light({addr, -1}); |
| 97 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && | 119 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && |
| 98 | (it->GetAddressArbiterKey() == addr)) { | 120 | (it->GetAddressArbiterKey() == addr)) { |
| 121 | // End the thread's wait. | ||
| 99 | KThread* target_thread = std::addressof(*it); | 122 | KThread* target_thread = std::addressof(*it); |
| 100 | target_thread->SetWaitResult(ResultSuccess); | 123 | target_thread->EndWait(ResultSuccess); |
| 101 | 124 | ||
| 102 | ASSERT(target_thread->IsWaitingForAddressArbiter()); | 125 | ASSERT(target_thread->IsWaitingForAddressArbiter()); |
| 103 | target_thread->Wakeup(); | 126 | target_thread->ClearAddressArbiter(); |
| 104 | 127 | ||
| 105 | it = thread_tree.erase(it); | 128 | it = thread_tree.erase(it); |
| 106 | target_thread->ClearAddressArbiter(); | ||
| 107 | ++num_waiters; | 129 | ++num_waiters; |
| 108 | } | 130 | } |
| 109 | } | 131 | } |
| @@ -129,14 +151,14 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 | |||
| 129 | auto it = thread_tree.nfind_light({addr, -1}); | 151 | auto it = thread_tree.nfind_light({addr, -1}); |
| 130 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && | 152 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && |
| 131 | (it->GetAddressArbiterKey() == addr)) { | 153 | (it->GetAddressArbiterKey() == addr)) { |
| 154 | // End the thread's wait. | ||
| 132 | KThread* target_thread = std::addressof(*it); | 155 | KThread* target_thread = std::addressof(*it); |
| 133 | target_thread->SetWaitResult(ResultSuccess); | 156 | target_thread->EndWait(ResultSuccess); |
| 134 | 157 | ||
| 135 | ASSERT(target_thread->IsWaitingForAddressArbiter()); | 158 | ASSERT(target_thread->IsWaitingForAddressArbiter()); |
| 136 | target_thread->Wakeup(); | 159 | target_thread->ClearAddressArbiter(); |
| 137 | 160 | ||
| 138 | it = thread_tree.erase(it); | 161 | it = thread_tree.erase(it); |
| 139 | target_thread->ClearAddressArbiter(); | ||
| 140 | ++num_waiters; | 162 | ++num_waiters; |
| 141 | } | 163 | } |
| 142 | } | 164 | } |
| @@ -197,14 +219,14 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 | |||
| 197 | 219 | ||
| 198 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && | 220 | while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) && |
| 199 | (it->GetAddressArbiterKey() == addr)) { | 221 | (it->GetAddressArbiterKey() == addr)) { |
| 222 | // End the thread's wait. | ||
| 200 | KThread* target_thread = std::addressof(*it); | 223 | KThread* target_thread = std::addressof(*it); |
| 201 | target_thread->SetWaitResult(ResultSuccess); | 224 | target_thread->EndWait(ResultSuccess); |
| 202 | 225 | ||
| 203 | ASSERT(target_thread->IsWaitingForAddressArbiter()); | 226 | ASSERT(target_thread->IsWaitingForAddressArbiter()); |
| 204 | target_thread->Wakeup(); | 227 | target_thread->ClearAddressArbiter(); |
| 205 | 228 | ||
| 206 | it = thread_tree.erase(it); | 229 | it = thread_tree.erase(it); |
| 207 | target_thread->ClearAddressArbiter(); | ||
| 208 | ++num_waiters; | 230 | ++num_waiters; |
| 209 | } | 231 | } |
| 210 | } | 232 | } |
| @@ -214,6 +236,7 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 | |||
| 214 | ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { | 236 | ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { |
| 215 | // Prepare to wait. | 237 | // Prepare to wait. |
| 216 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); | 238 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 239 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); | ||
| 217 | 240 | ||
| 218 | { | 241 | { |
| 219 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; | 242 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; |
| @@ -224,9 +247,6 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement | |||
| 224 | return ResultTerminationRequested; | 247 | return ResultTerminationRequested; |
| 225 | } | 248 | } |
| 226 | 249 | ||
| 227 | // Set the synced object. | ||
| 228 | cur_thread->SetWaitResult(ResultTimedOut); | ||
| 229 | |||
| 230 | // Read the value from userspace. | 250 | // Read the value from userspace. |
| 231 | s32 user_value{}; | 251 | s32 user_value{}; |
| 232 | bool succeeded{}; | 252 | bool succeeded{}; |
| @@ -256,21 +276,10 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement | |||
| 256 | // Set the arbiter. | 276 | // Set the arbiter. |
| 257 | cur_thread->SetAddressArbiter(&thread_tree, addr); | 277 | cur_thread->SetAddressArbiter(&thread_tree, addr); |
| 258 | thread_tree.insert(*cur_thread); | 278 | thread_tree.insert(*cur_thread); |
| 259 | cur_thread->SetState(ThreadState::Waiting); | ||
| 260 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); | ||
| 261 | } | ||
| 262 | 279 | ||
| 263 | // Cancel the timer wait. | 280 | // Wait for the thread to finish. |
| 264 | kernel.TimeManager().UnscheduleTimeEvent(cur_thread); | 281 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 265 | 282 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); | |
| 266 | // Remove from the address arbiter. | ||
| 267 | { | ||
| 268 | KScopedSchedulerLock sl(kernel); | ||
| 269 | |||
| 270 | if (cur_thread->IsWaitingForAddressArbiter()) { | ||
| 271 | thread_tree.erase(thread_tree.iterator_to(*cur_thread)); | ||
| 272 | cur_thread->ClearAddressArbiter(); | ||
| 273 | } | ||
| 274 | } | 283 | } |
| 275 | 284 | ||
| 276 | // Get the result. | 285 | // Get the result. |
| @@ -280,6 +289,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement | |||
| 280 | ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | 289 | ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { |
| 281 | // Prepare to wait. | 290 | // Prepare to wait. |
| 282 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); | 291 | KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread(); |
| 292 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); | ||
| 283 | 293 | ||
| 284 | { | 294 | { |
| 285 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; | 295 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; |
| @@ -290,9 +300,6 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | |||
| 290 | return ResultTerminationRequested; | 300 | return ResultTerminationRequested; |
| 291 | } | 301 | } |
| 292 | 302 | ||
| 293 | // Set the synced object. | ||
| 294 | cur_thread->SetWaitResult(ResultTimedOut); | ||
| 295 | |||
| 296 | // Read the value from userspace. | 303 | // Read the value from userspace. |
| 297 | s32 user_value{}; | 304 | s32 user_value{}; |
| 298 | if (!ReadFromUser(system, &user_value, addr)) { | 305 | if (!ReadFromUser(system, &user_value, addr)) { |
| @@ -315,21 +322,10 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | |||
| 315 | // Set the arbiter. | 322 | // Set the arbiter. |
| 316 | cur_thread->SetAddressArbiter(&thread_tree, addr); | 323 | cur_thread->SetAddressArbiter(&thread_tree, addr); |
| 317 | thread_tree.insert(*cur_thread); | 324 | thread_tree.insert(*cur_thread); |
| 318 | cur_thread->SetState(ThreadState::Waiting); | ||
| 319 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); | ||
| 320 | } | ||
| 321 | |||
| 322 | // Cancel the timer wait. | ||
| 323 | kernel.TimeManager().UnscheduleTimeEvent(cur_thread); | ||
| 324 | 325 | ||
| 325 | // Remove from the address arbiter. | 326 | // Wait for the thread to finish. |
| 326 | { | 327 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 327 | KScopedSchedulerLock sl(kernel); | 328 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); |
| 328 | |||
| 329 | if (cur_thread->IsWaitingForAddressArbiter()) { | ||
| 330 | thread_tree.erase(thread_tree.iterator_to(*cur_thread)); | ||
| 331 | cur_thread->ClearAddressArbiter(); | ||
| 332 | } | ||
| 333 | } | 329 | } |
| 334 | 330 | ||
| 335 | // Get the result. | 331 | // Get the result. |