mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-09-03 07:59:01 +00:00
Merge pull request #9923 from liamwhite/kht
kernel: add timer pointer to KThreadQueue
This commit is contained in:
commit
92c89312fc
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -1290,9 +1290,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()) {
|
||||||
@ -1301,6 +1302,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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user