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) {
// 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);
}

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) {
// 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);

View file

@ -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));
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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 {