diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_condition_variable.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 15 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_synchronization_object.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread_queue.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread_queue.h | 10 |
8 files changed, 42 insertions, 15 deletions
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index fb86451ea..a4c16eca9 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp | |||
| @@ -237,10 +237,11 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 val | |||
| 237 | Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { | 237 | Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { |
| 238 | // Prepare to wait. | 238 | // Prepare to wait. |
| 239 | KThread* cur_thread = GetCurrentThreadPointer(kernel); | 239 | KThread* cur_thread = GetCurrentThreadPointer(kernel); |
| 240 | KHardwareTimer* timer{}; | ||
| 240 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); | 241 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); |
| 241 | 242 | ||
| 242 | { | 243 | { |
| 243 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; | 244 | KScopedSchedulerLockAndSleep slp{kernel, std::addressof(timer), cur_thread, timeout}; |
| 244 | 245 | ||
| 245 | // Check that the thread isn't terminating. | 246 | // Check that the thread isn't terminating. |
| 246 | if (cur_thread->IsTerminationRequested()) { | 247 | if (cur_thread->IsTerminationRequested()) { |
| @@ -279,6 +280,7 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6 | |||
| 279 | thread_tree.insert(*cur_thread); | 280 | thread_tree.insert(*cur_thread); |
| 280 | 281 | ||
| 281 | // Wait for the thread to finish. | 282 | // Wait for the thread to finish. |
| 283 | wait_queue.SetHardwareTimer(timer); | ||
| 282 | cur_thread->BeginWait(std::addressof(wait_queue)); | 284 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 283 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); | 285 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); |
| 284 | } | 286 | } |
| @@ -290,10 +292,11 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6 | |||
| 290 | Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | 292 | Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { |
| 291 | // Prepare to wait. | 293 | // Prepare to wait. |
| 292 | KThread* cur_thread = GetCurrentThreadPointer(kernel); | 294 | KThread* cur_thread = GetCurrentThreadPointer(kernel); |
| 295 | KHardwareTimer* timer{}; | ||
| 293 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); | 296 | ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); |
| 294 | 297 | ||
| 295 | { | 298 | { |
| 296 | KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; | 299 | KScopedSchedulerLockAndSleep slp{kernel, std::addressof(timer), cur_thread, timeout}; |
| 297 | 300 | ||
| 298 | // Check that the thread isn't terminating. | 301 | // Check that the thread isn't terminating. |
| 299 | if (cur_thread->IsTerminationRequested()) { | 302 | if (cur_thread->IsTerminationRequested()) { |
| @@ -325,6 +328,7 @@ Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { | |||
| 325 | thread_tree.insert(*cur_thread); | 328 | thread_tree.insert(*cur_thread); |
| 326 | 329 | ||
| 327 | // Wait for the thread to finish. | 330 | // Wait for the thread to finish. |
| 331 | wait_queue.SetHardwareTimer(timer); | ||
| 328 | cur_thread->BeginWait(std::addressof(wait_queue)); | 332 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 329 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); | 333 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); |
| 330 | } | 334 | } |
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index f40cf92b1..458f4c94e 100644 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp | |||
| @@ -266,11 +266,12 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) { | |||
| 266 | Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { | 266 | Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { |
| 267 | // Prepare to wait. | 267 | // Prepare to wait. |
| 268 | KThread* cur_thread = GetCurrentThreadPointer(kernel); | 268 | KThread* cur_thread = GetCurrentThreadPointer(kernel); |
| 269 | KHardwareTimer* timer{}; | ||
| 269 | ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( | 270 | ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( |
| 270 | kernel, std::addressof(thread_tree)); | 271 | kernel, std::addressof(thread_tree)); |
| 271 | 272 | ||
| 272 | { | 273 | { |
| 273 | KScopedSchedulerLockAndSleep slp(kernel, cur_thread, timeout); | 274 | KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), cur_thread, timeout); |
| 274 | 275 | ||
| 275 | // Check that the thread isn't terminating. | 276 | // Check that the thread isn't terminating. |
| 276 | if (cur_thread->IsTerminationRequested()) { | 277 | if (cur_thread->IsTerminationRequested()) { |
| @@ -320,6 +321,7 @@ Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { | |||
| 320 | thread_tree.insert(*cur_thread); | 321 | thread_tree.insert(*cur_thread); |
| 321 | 322 | ||
| 322 | // Begin waiting. | 323 | // Begin waiting. |
| 324 | wait_queue.SetHardwareTimer(timer); | ||
| 323 | cur_thread->BeginWait(std::addressof(wait_queue)); | 325 | cur_thread->BeginWait(std::addressof(wait_queue)); |
| 324 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); | 326 | cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); |
| 325 | cur_thread->SetMutexWaitAddressForDebugging(addr); | 327 | cur_thread->SetMutexWaitAddressForDebugging(addr); |
diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp index cade99cfd..8fce2bc71 100644 --- a/src/core/hle/kernel/k_light_condition_variable.cpp +++ b/src/core/hle/kernel/k_light_condition_variable.cpp | |||
| @@ -40,13 +40,14 @@ private: | |||
| 40 | void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { | 40 | void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { |
| 41 | // Create thread queue. | 41 | // Create thread queue. |
| 42 | KThread* owner = GetCurrentThreadPointer(kernel); | 42 | KThread* owner = GetCurrentThreadPointer(kernel); |
| 43 | KHardwareTimer* timer{}; | ||
| 43 | 44 | ||
| 44 | ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), | 45 | ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), |
| 45 | allow_terminating_thread); | 46 | allow_terminating_thread); |
| 46 | 47 | ||
| 47 | // Sleep the thread. | 48 | // Sleep the thread. |
| 48 | { | 49 | { |
| 49 | KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); | 50 | KScopedSchedulerLockAndSleep lk(kernel, std::addressof(timer), owner, timeout); |
| 50 | 51 | ||
| 51 | if (!allow_terminating_thread && owner->IsTerminationRequested()) { | 52 | if (!allow_terminating_thread && owner->IsTerminationRequested()) { |
| 52 | lk.CancelSleep(); | 53 | lk.CancelSleep(); |
| @@ -59,6 +60,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter | |||
| 59 | wait_list.push_back(*owner); | 60 | wait_list.push_back(*owner); |
| 60 | 61 | ||
| 61 | // Begin waiting. | 62 | // Begin waiting. |
| 63 | wait_queue.SetHardwareTimer(timer); | ||
| 62 | owner->BeginWait(std::addressof(wait_queue)); | 64 | owner->BeginWait(std::addressof(wait_queue)); |
| 63 | } | 65 | } |
| 64 | 66 | ||
diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index 76db65a4d..14b83a819 100644 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | |||
| @@ -13,16 +13,22 @@ namespace Kernel { | |||
| 13 | 13 | ||
| 14 | class [[nodiscard]] KScopedSchedulerLockAndSleep { | 14 | class [[nodiscard]] KScopedSchedulerLockAndSleep { |
| 15 | public: | 15 | public: |
| 16 | explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout) | 16 | explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KHardwareTimer** out_timer, |
| 17 | : kernel(kernel_), thread(t), timeout_tick(timeout) { | 17 | KThread* t, s64 timeout) |
| 18 | : kernel(kernel_), timeout_tick(timeout), thread(t), timer() { | ||
| 18 | // Lock the scheduler. | 19 | // Lock the scheduler. |
| 19 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); | 20 | kernel.GlobalSchedulerContext().scheduler_lock.Lock(); |
| 21 | |||
| 22 | // Set our timer only if the time is positive. | ||
| 23 | timer = (timeout_tick > 0) ? std::addressof(kernel.HardwareTimer()) : nullptr; | ||
| 24 | |||
| 25 | *out_timer = timer; | ||
| 20 | } | 26 | } |
| 21 | 27 | ||
| 22 | ~KScopedSchedulerLockAndSleep() { | 28 | ~KScopedSchedulerLockAndSleep() { |
| 23 | // Register the sleep. | 29 | // Register the sleep. |
| 24 | if (timeout_tick > 0) { | 30 | if (timeout_tick > 0) { |
| 25 | kernel.HardwareTimer().RegisterTask(thread, timeout_tick); | 31 | timer->RegisterTask(thread, timeout_tick); |
| 26 | } | 32 | } |
| 27 | 33 | ||
| 28 | // Unlock the scheduler. | 34 | // Unlock the scheduler. |
| @@ -35,8 +41,9 @@ public: | |||
| 35 | 41 | ||
| 36 | private: | 42 | private: |
| 37 | KernelCore& kernel; | 43 | KernelCore& kernel; |
| 38 | KThread* thread{}; | ||
| 39 | s64 timeout_tick{}; | 44 | s64 timeout_tick{}; |
| 45 | KThread* thread{}; | ||
| 46 | KHardwareTimer* timer{}; | ||
| 40 | }; | 47 | }; |
| 41 | 48 | ||
| 42 | } // namespace Kernel | 49 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp index 802dca046..40fd0c038 100644 --- a/src/core/hle/kernel/k_synchronization_object.cpp +++ b/src/core/hle/kernel/k_synchronization_object.cpp | |||
| @@ -79,12 +79,13 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, | |||
| 79 | 79 | ||
| 80 | // Prepare for wait. | 80 | // Prepare for wait. |
| 81 | KThread* thread = GetCurrentThreadPointer(kernel_ctx); | 81 | KThread* thread = GetCurrentThreadPointer(kernel_ctx); |
| 82 | KHardwareTimer* timer{}; | ||
| 82 | ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects, | 83 | ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects, |
| 83 | thread_nodes.data(), num_objects); | 84 | thread_nodes.data(), num_objects); |
| 84 | 85 | ||
| 85 | { | 86 | { |
| 86 | // Setup the scheduling lock and sleep. | 87 | // Setup the scheduling lock and sleep. |
| 87 | KScopedSchedulerLockAndSleep slp(kernel_ctx, thread, timeout); | 88 | KScopedSchedulerLockAndSleep slp(kernel_ctx, std::addressof(timer), thread, timeout); |
| 88 | 89 | ||
| 89 | // Check if the thread should terminate. | 90 | // Check if the thread should terminate. |
| 90 | if (thread->IsTerminationRequested()) { | 91 | if (thread->IsTerminationRequested()) { |
| @@ -131,6 +132,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index, | |||
| 131 | thread->SetSyncedIndex(-1); | 132 | thread->SetSyncedIndex(-1); |
| 132 | 133 | ||
| 133 | // Wait for an object to be signaled. | 134 | // Wait for an object to be signaled. |
| 135 | wait_queue.SetHardwareTimer(timer); | ||
| 134 | thread->BeginWait(std::addressof(wait_queue)); | 136 | thread->BeginWait(std::addressof(wait_queue)); |
| 135 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); | 137 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); |
| 136 | } | 138 | } |
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 15ae652f9..26e3700e4 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -1290,9 +1290,10 @@ Result KThread::Sleep(s64 timeout) { | |||
| 1290 | ASSERT(timeout > 0); | 1290 | ASSERT(timeout > 0); |
| 1291 | 1291 | ||
| 1292 | ThreadQueueImplForKThreadSleep wait_queue_(kernel); | 1292 | ThreadQueueImplForKThreadSleep wait_queue_(kernel); |
| 1293 | KHardwareTimer* timer{}; | ||
| 1293 | { | 1294 | { |
| 1294 | // Setup the scheduling lock and sleep. | 1295 | // Setup the scheduling lock and sleep. |
| 1295 | KScopedSchedulerLockAndSleep slp(kernel, this, timeout); | 1296 | KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), this, timeout); |
| 1296 | 1297 | ||
| 1297 | // Check if the thread should terminate. | 1298 | // Check if the thread should terminate. |
| 1298 | if (this->IsTerminationRequested()) { | 1299 | if (this->IsTerminationRequested()) { |
| @@ -1301,6 +1302,7 @@ Result KThread::Sleep(s64 timeout) { | |||
| 1301 | } | 1302 | } |
| 1302 | 1303 | ||
| 1303 | // Wait for the sleep to end. | 1304 | // Wait for the sleep to end. |
| 1305 | wait_queue_.SetHardwareTimer(timer); | ||
| 1304 | this->BeginWait(std::addressof(wait_queue_)); | 1306 | this->BeginWait(std::addressof(wait_queue_)); |
| 1305 | SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); | 1307 | SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); |
| 1306 | } | 1308 | } |
diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 5f1dc97eb..fe648447b 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp | |||
| @@ -22,7 +22,9 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { | |||
| 22 | waiting_thread->ClearWaitQueue(); | 22 | waiting_thread->ClearWaitQueue(); |
| 23 | 23 | ||
| 24 | // Cancel the thread task. | 24 | // Cancel the thread task. |
| 25 | kernel.HardwareTimer().CancelTask(waiting_thread); | 25 | if (m_hardware_timer != nullptr) { |
| 26 | m_hardware_timer->CancelTask(waiting_thread); | ||
| 27 | } | ||
| 26 | } | 28 | } |
| 27 | 29 | ||
| 28 | void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { | 30 | void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { |
| @@ -36,8 +38,8 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool | |||
| 36 | waiting_thread->ClearWaitQueue(); | 38 | waiting_thread->ClearWaitQueue(); |
| 37 | 39 | ||
| 38 | // Cancel the thread task. | 40 | // Cancel the thread task. |
| 39 | if (cancel_timer_task) { | 41 | if (cancel_timer_task && m_hardware_timer != nullptr) { |
| 40 | kernel.HardwareTimer().CancelTask(waiting_thread); | 42 | m_hardware_timer->CancelTask(waiting_thread); |
| 41 | } | 43 | } |
| 42 | } | 44 | } |
| 43 | 45 | ||
diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 8d76ece81..01e330e2e 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h | |||
| @@ -8,11 +8,17 @@ | |||
| 8 | 8 | ||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | class KHardwareTimer; | ||
| 12 | |||
| 11 | class KThreadQueue { | 13 | class KThreadQueue { |
| 12 | public: | 14 | public: |
| 13 | explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} | 15 | explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_}, m_hardware_timer{} {} |
| 14 | virtual ~KThreadQueue() = default; | 16 | virtual ~KThreadQueue() = default; |
| 15 | 17 | ||
| 18 | void SetHardwareTimer(KHardwareTimer* timer) { | ||
| 19 | m_hardware_timer = timer; | ||
| 20 | } | ||
| 21 | |||
| 16 | virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, | 22 | virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, |
| 17 | Result wait_result); | 23 | Result wait_result); |
| 18 | virtual void EndWait(KThread* waiting_thread, Result wait_result); | 24 | virtual void EndWait(KThread* waiting_thread, Result wait_result); |
| @@ -20,7 +26,7 @@ public: | |||
| 20 | 26 | ||
| 21 | private: | 27 | private: |
| 22 | KernelCore& kernel; | 28 | KernelCore& kernel; |
| 23 | KThread::WaiterList wait_list{}; | 29 | KHardwareTimer* m_hardware_timer{}; |
| 24 | }; | 30 | }; |
| 25 | 31 | ||
| 26 | class KThreadQueueWithoutEndWait : public KThreadQueue { | 32 | class KThreadQueueWithoutEndWait : public KThreadQueue { |