mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-09-03 06:39:02 +00:00
kernel: add timer pointer to KThreadQueue
This commit is contained in:
parent
a7792e5ff8
commit
1776448df2
@ -237,10 +237,11 @@ Result KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 val
|
||||
Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) {
|
||||
// Prepare to wait.
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
KHardwareTimer* timer{};
|
||||
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.
|
||||
if (cur_thread->IsTerminationRequested()) {
|
||||
@ -279,6 +280,7 @@ Result KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s6
|
||||
thread_tree.insert(*cur_thread);
|
||||
|
||||
// Wait for the thread to finish.
|
||||
wait_queue.SetHardwareTimer(timer);
|
||||
cur_thread->BeginWait(std::addressof(wait_queue));
|
||||
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) {
|
||||
// Prepare to wait.
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
KHardwareTimer* timer{};
|
||||
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.
|
||||
if (cur_thread->IsTerminationRequested()) {
|
||||
@ -325,6 +328,7 @@ Result KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
|
||||
thread_tree.insert(*cur_thread);
|
||||
|
||||
// Wait for the thread to finish.
|
||||
wait_queue.SetHardwareTimer(timer);
|
||||
cur_thread->BeginWait(std::addressof(wait_queue));
|
||||
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
|
||||
}
|
||||
|
@ -266,11 +266,12 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
|
||||
Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
|
||||
// Prepare to wait.
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
KHardwareTimer* timer{};
|
||||
ThreadQueueImplForKConditionVariableWaitConditionVariable 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.
|
||||
if (cur_thread->IsTerminationRequested()) {
|
||||
@ -320,6 +321,7 @@ Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
|
||||
thread_tree.insert(*cur_thread);
|
||||
|
||||
// Begin waiting.
|
||||
wait_queue.SetHardwareTimer(timer);
|
||||
cur_thread->BeginWait(std::addressof(wait_queue));
|
||||
cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
|
||||
cur_thread->SetMutexWaitAddressForDebugging(addr);
|
||||
|
@ -40,13 +40,14 @@ private:
|
||||
void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) {
|
||||
// Create thread queue.
|
||||
KThread* owner = GetCurrentThreadPointer(kernel);
|
||||
KHardwareTimer* timer{};
|
||||
|
||||
ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list),
|
||||
allow_terminating_thread);
|
||||
|
||||
// Sleep the thread.
|
||||
{
|
||||
KScopedSchedulerLockAndSleep lk(kernel, owner, timeout);
|
||||
KScopedSchedulerLockAndSleep lk(kernel, std::addressof(timer), owner, timeout);
|
||||
|
||||
if (!allow_terminating_thread && owner->IsTerminationRequested()) {
|
||||
lk.CancelSleep();
|
||||
@ -59,6 +60,7 @@ void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_ter
|
||||
wait_list.push_back(*owner);
|
||||
|
||||
// Begin waiting.
|
||||
wait_queue.SetHardwareTimer(timer);
|
||||
owner->BeginWait(std::addressof(wait_queue));
|
||||
}
|
||||
|
||||
|
@ -13,16 +13,22 @@ namespace Kernel {
|
||||
|
||||
class [[nodiscard]] KScopedSchedulerLockAndSleep {
|
||||
public:
|
||||
explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KThread* t, s64 timeout)
|
||||
: kernel(kernel_), thread(t), timeout_tick(timeout) {
|
||||
explicit KScopedSchedulerLockAndSleep(KernelCore& kernel_, KHardwareTimer** out_timer,
|
||||
KThread* t, s64 timeout)
|
||||
: kernel(kernel_), timeout_tick(timeout), thread(t), timer() {
|
||||
// Lock the scheduler.
|
||||
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() {
|
||||
// Register the sleep.
|
||||
if (timeout_tick > 0) {
|
||||
kernel.HardwareTimer().RegisterTask(thread, timeout_tick);
|
||||
timer->RegisterTask(thread, timeout_tick);
|
||||
}
|
||||
|
||||
// Unlock the scheduler.
|
||||
@ -35,8 +41,9 @@ public:
|
||||
|
||||
private:
|
||||
KernelCore& kernel;
|
||||
KThread* thread{};
|
||||
s64 timeout_tick{};
|
||||
KThread* thread{};
|
||||
KHardwareTimer* timer{};
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
@ -79,12 +79,13 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
|
||||
|
||||
// Prepare for wait.
|
||||
KThread* thread = GetCurrentThreadPointer(kernel_ctx);
|
||||
KHardwareTimer* timer{};
|
||||
ThreadQueueImplForKSynchronizationObjectWait wait_queue(kernel_ctx, objects,
|
||||
thread_nodes.data(), num_objects);
|
||||
|
||||
{
|
||||
// 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.
|
||||
if (thread->IsTerminationRequested()) {
|
||||
@ -131,6 +132,7 @@ Result KSynchronizationObject::Wait(KernelCore& kernel_ctx, s32* out_index,
|
||||
thread->SetSyncedIndex(-1);
|
||||
|
||||
// Wait for an object to be signaled.
|
||||
wait_queue.SetHardwareTimer(timer);
|
||||
thread->BeginWait(std::addressof(wait_queue));
|
||||
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
|
||||
}
|
||||
|
@ -1268,9 +1268,10 @@ Result KThread::Sleep(s64 timeout) {
|
||||
ASSERT(timeout > 0);
|
||||
|
||||
ThreadQueueImplForKThreadSleep wait_queue_(kernel);
|
||||
KHardwareTimer* timer{};
|
||||
{
|
||||
// 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.
|
||||
if (this->IsTerminationRequested()) {
|
||||
@ -1279,6 +1280,7 @@ Result KThread::Sleep(s64 timeout) {
|
||||
}
|
||||
|
||||
// Wait for the sleep to end.
|
||||
wait_queue_.SetHardwareTimer(timer);
|
||||
this->BeginWait(std::addressof(wait_queue_));
|
||||
SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
|
||||
waiting_thread->ClearWaitQueue();
|
||||
|
||||
// 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) {
|
||||
@ -36,8 +38,8 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool
|
||||
waiting_thread->ClearWaitQueue();
|
||||
|
||||
// Cancel the thread task.
|
||||
if (cancel_timer_task) {
|
||||
kernel.HardwareTimer().CancelTask(waiting_thread);
|
||||
if (cancel_timer_task && m_hardware_timer != nullptr) {
|
||||
m_hardware_timer->CancelTask(waiting_thread);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,17 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class KHardwareTimer;
|
||||
|
||||
class KThreadQueue {
|
||||
public:
|
||||
explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_} {}
|
||||
explicit KThreadQueue(KernelCore& kernel_) : kernel{kernel_}, m_hardware_timer{} {}
|
||||
virtual ~KThreadQueue() = default;
|
||||
|
||||
void SetHardwareTimer(KHardwareTimer* timer) {
|
||||
m_hardware_timer = timer;
|
||||
}
|
||||
|
||||
virtual void NotifyAvailable(KThread* waiting_thread, KSynchronizationObject* signaled_object,
|
||||
Result wait_result);
|
||||
virtual void EndWait(KThread* waiting_thread, Result wait_result);
|
||||
@ -20,7 +26,7 @@ public:
|
||||
|
||||
private:
|
||||
KernelCore& kernel;
|
||||
KThread::WaiterList wait_list{};
|
||||
KHardwareTimer* m_hardware_timer{};
|
||||
};
|
||||
|
||||
class KThreadQueueWithoutEndWait : public KThreadQueue {
|
||||
|
Loading…
Reference in New Issue
Block a user