2
1
Fork 0
mirror of https://github.com/yuzu-emu/yuzu.git synced 2024-07-04 23:31:19 +01:00

kernel: add timer pointer to KThreadQueue

This commit is contained in:
Liam 2023-03-07 20:48:46 -05:00
parent a7792e5ff8
commit 1776448df2
8 changed files with 42 additions and 15 deletions

View file

@ -237,10 +237,11 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 val
Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) { Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(kernel); KThread* cur_thread = GetCurrentThreadPointer(kernel);
KHardwareTimer* timer{};
ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
{ {
KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; KScopedSchedulerLockAndSleep slp{kernel, std::addressof(timer), cur_thread, timeout};
// Check that the thread isn't terminating. // Check that the thread isn't terminating.
if (cur_thread->IsTerminationRequested()) { if (cur_thread->IsTerminationRequested()) {
@ -279,6 +280,7 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6
thread_tree.insert(*cur_thread); thread_tree.insert(*cur_thread);
// Wait for the thread to finish. // Wait for the thread to finish.
wait_queue.SetHardwareTimer(timer);
cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->BeginWait(std::addressof(wait_queue));
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
} }
@ -290,10 +292,11 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6
Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(kernel); KThread* cur_thread = GetCurrentThreadPointer(kernel);
KHardwareTimer* timer{};
ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree)); ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
{ {
KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout}; KScopedSchedulerLockAndSleep slp{kernel, std::addressof(timer), cur_thread, timeout};
// Check that the thread isn't terminating. // Check that the thread isn't terminating.
if (cur_thread->IsTerminationRequested()) { if (cur_thread->IsTerminationRequested()) {
@ -325,6 +328,7 @@ Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
thread_tree.insert(*cur_thread); thread_tree.insert(*cur_thread);
// Wait for the thread to finish. // Wait for the thread to finish.
wait_queue.SetHardwareTimer(timer);
cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->BeginWait(std::addressof(wait_queue));
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
} }

View file

@ -266,11 +266,12 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) { Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
// Prepare to wait. // Prepare to wait.
KThread* cur_thread = GetCurrentThreadPointer(kernel); KThread* cur_thread = GetCurrentThreadPointer(kernel);
KHardwareTimer* timer{};
ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue( ThreadQueueImplForKConditionVariableWaitConditionVariable wait_queue(
kernel, std::addressof(thread_tree)); kernel, std::addressof(thread_tree));
{ {
KScopedSchedulerLockAndSleep slp(kernel, cur_thread, timeout); KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), cur_thread, timeout);
// Check that the thread isn't terminating. // Check that the thread isn't terminating.
if (cur_thread->IsTerminationRequested()) { if (cur_thread->IsTerminationRequested()) {
@ -320,6 +321,7 @@ Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
thread_tree.insert(*cur_thread); thread_tree.insert(*cur_thread);
// Begin waiting. // Begin waiting.
wait_queue.SetHardwareTimer(timer);
cur_thread->BeginWait(std::addressof(wait_queue)); cur_thread->BeginWait(std::addressof(wait_queue));
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
cur_thread->SetMutexWaitAddressForDebugging(addr); cur_thread->SetMutexWaitAddressForDebugging(addr);

View file

@ -40,13 +40,14 @@ private:
void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
// Create thread queue. // Create thread queue.
KThread* owner = GetCurrentThreadPointer(kernel); KThread* owner = GetCurrentThreadPointer(kernel);
KHardwareTimer* timer{};
ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list),
allow_terminating_thread); allow_terminating_thread);
// Sleep the thread. // Sleep the thread.
{ {
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); KScopedSchedulerLockAndSleep lk(kernel, std::addressof(timer), owner, timeout);
if (!allow_terminating_thread && owner->IsTerminationRequested()) { if (!allow_terminating_thread && owner->IsTerminationRequested()) {
lk.CancelSleep(); lk.CancelSleep();
@ -59,6 +60,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter
wait_list.push_back(*owner); wait_list.push_back(*owner);
// Begin waiting. // Begin waiting.
wait_queue.SetHardwareTimer(timer);
owner->BeginWait(std::addressof(wait_queue)); owner->BeginWait(std::addressof(wait_queue));
} }

View file

@ -13,16 +13,22 @@ namespace Kernel {
class [[nodiscard]] KScopedSchedulerLockAndSleep { class [[nodiscard]] KScopedSchedulerLockAndSleep {
public: public:
explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout) explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KHardwareTimer** out_timer,
: kernel(kernel_), thread(t), timeout_tick(timeout) { KThread* t, s64 timeout)
: kernel(kernel_), timeout_tick(timeout), thread(t), timer() {
// Lock the scheduler. // Lock the scheduler.
kernel.GlobalSchedulerContext().scheduler_lock.Lock(); kernel.GlobalSchedulerContext().scheduler_lock.Lock();
// Set our timer only if the time is positive.
timer = (timeout_tick > 0) ? std::addressof(kernel.HardwareTimer()) : nullptr;
*out_timer = timer;
} }
~KScopedSchedulerLockAndSleep() { ~KScopedSchedulerLockAndSleep() {
// Register the sleep. // Register the sleep.
if (timeout_tick > 0) { if (timeout_tick > 0) {
kernel.HardwareTimer().RegisterTask(thread, timeout_tick); timer->RegisterTask(thread, timeout_tick);
} }
// Unlock the scheduler. // Unlock the scheduler.
@ -35,8 +41,9 @@ public:
private: private:
KernelCore& kernel; KernelCore& kernel;
KThread* thread{};
s64 timeout_tick{}; s64 timeout_tick{};
KThread* thread{};
KHardwareTimer* timer{};
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -79,12 +79,13 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
// Prepare for wait. // Prepare for wait.
KThread* thread = GetCurrentThreadPointer(kernel_ctx); KThread* thread = GetCurrentThreadPointer(kernel_ctx);
KHardwareTimer* timer{};
ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects, ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects,
thread_nodes.data(), num_objects); thread_nodes.data(), num_objects);
{ {
// Setup the scheduling lock and sleep. // Setup the scheduling lock and sleep.
KScopedSchedulerLockAndSleep slp(kernel_ctx, thread, timeout); KScopedSchedulerLockAndSleep slp(kernel_ctx, std::addressof(timer), thread, timeout);
// Check if the thread should terminate. // Check if the thread should terminate.
if (thread->IsTerminationRequested()) { if (thread->IsTerminationRequested()) {
@ -131,6 +132,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
thread->SetSyncedIndex(-1); thread->SetSyncedIndex(-1);
// Wait for an object to be signaled. // Wait for an object to be signaled.
wait_queue.SetHardwareTimer(timer);
thread->BeginWait(std::addressof(wait_queue)); thread->BeginWait(std::addressof(wait_queue));
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization); thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
} }

View file

@ -1268,9 +1268,10 @@ Result KThread::Sleep(s64 timeout) {
ASSERT(timeout > 0); ASSERT(timeout > 0);
ThreadQueueImplForKThreadSleep wait_queue_(kernel); ThreadQueueImplForKThreadSleep wait_queue_(kernel);
KHardwareTimer* timer{};
{ {
// Setup the scheduling lock and sleep. // Setup the scheduling lock and sleep.
KScopedSchedulerLockAndSleep slp(kernel, this, timeout); KScopedSchedulerLockAndSleep slp(kernel, std::addressof(timer), this, timeout);
// Check if the thread should terminate. // Check if the thread should terminate.
if (this->IsTerminationRequested()) { if (this->IsTerminationRequested()) {
@ -1279,6 +1280,7 @@ Result KThread::Sleep(s64 timeout) {
} }
// Wait for the sleep to end. // Wait for the sleep to end.
wait_queue_.SetHardwareTimer(timer);
this->BeginWait(std::addressof(wait_queue_)); this->BeginWait(std::addressof(wait_queue_));
SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep); SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
} }

View file

@ -22,7 +22,9 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
waiting_thread->ClearWaitQueue(); waiting_thread->ClearWaitQueue();
// Cancel the thread task. // Cancel the thread task.
kernel.HardwareTimer().CancelTask(waiting_thread); if (m_hardware_timer != nullptr) {
m_hardware_timer->CancelTask(waiting_thread);
}
} }
void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { 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
waiting_thread->ClearWaitQueue(); waiting_thread->ClearWaitQueue();
// Cancel the thread task. // Cancel the thread task.
if (cancel_timer_task) { if (cancel_timer_task && m_hardware_timer != nullptr) {
kernel.HardwareTimer().CancelTask(waiting_thread); m_hardware_timer->CancelTask(waiting_thread);
} }
} }

View file

@ -8,11 +8,17 @@
namespace Kernel { namespace Kernel {
class KHardwareTimer;
class KThreadQueue { class KThreadQueue {
public: public:
explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {} explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_}, m_hardware_timer{} {}
virtual ~KThreadQueue() = default; virtual ~KThreadQueue() = default;
void SetHardwareTimer(KHardwareTimer* timer) {
m_hardware_timer = timer;
}
virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object, virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object,
Result wait_result); Result wait_result);
virtual void EndWait(KThread* waiting_thread, Result wait_result); virtual void EndWait(KThread* waiting_thread, Result wait_result);
@ -20,7 +26,7 @@ public:
private: private:
KernelCore& kernel; KernelCore& kernel;
KThread::WaiterList wait_list{}; KHardwareTimer* m_hardware_timer{};
}; };
class KThreadQueueWithoutEndWait : public KThreadQueue { class KThreadQueueWithoutEndWait : public KThreadQueue {