diff options
| author | bunnei <bunneidev@gmail.com> | 2021-11-09 20:54:44 -0800 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2021-12-06 16:39:17 -0800 | 
| commit | 5dff28290fc4fc9bc3db3c32476dd93b2c4414c6 (patch) | |
| tree | 45bccef430ad51ccef88b66036f511d8f52964d0 /src/core/hle/kernel | |
| parent | 423acf53b740ce96ca37988aad79ddf5013645ef (diff) | |
hle: kernel: KLightConditionVariable: Migrate to updated KThreadQueue.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.cpp | 80 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.h | 60 | 
2 files changed, 86 insertions, 54 deletions
| diff --git a/src/core/hle/kernel/k_light_condition_variable.cpp b/src/core/hle/kernel/k_light_condition_variable.cpp new file mode 100644 index 000000000..9ff710084 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.cpp @@ -0,0 +1,80 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/kernel/k_light_condition_variable.h" +#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" +#include "core/hle/kernel/k_thread_queue.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel { + +namespace { + +class ThreadQueueImplForKLightConditionVariable final : public KThreadQueue { +private: +    KThread::WaiterList* m_wait_list; +    bool m_allow_terminating_thread; + +public: +    ThreadQueueImplForKLightConditionVariable(KernelCore& kernel_, KThread::WaiterList* wl, +                                              bool term) +        : KThreadQueue(kernel_), m_wait_list(wl), m_allow_terminating_thread(term) {} + +    virtual void CancelWait(KThread* waiting_thread, ResultCode wait_result, +                            bool cancel_timer_task) override { +        // Only process waits if we're allowed to. +        if (ResultTerminationRequested == wait_result && m_allow_terminating_thread) { +            return; +        } + +        // Remove the thread from the waiting thread from the light condition variable. +        m_wait_list->erase(m_wait_list->iterator_to(*waiting_thread)); + +        // Invoke the base cancel wait handler. +        KThreadQueue::CancelWait(waiting_thread, wait_result, cancel_timer_task); +    } +}; + +} // namespace + +void KLightConditionVariable::Wait(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { +    // Create thread queue. +    KThread* owner = GetCurrentThreadPointer(kernel); + +    ThreadQueueImplForKLightConditionVariable wait_queue(kernel, std::addressof(wait_list), +                                                         allow_terminating_thread); + +    // Sleep the thread. +    { +        KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); + +        if (!allow_terminating_thread && owner->IsTerminationRequested()) { +            lk.CancelSleep(); +            return; +        } + +        lock->Unlock(); + +        // Add the thread to the queue. +        wait_list.push_back(*owner); + +        // Begin waiting. +        owner->BeginWait(std::addressof(wait_queue)); +    } + +    // Re-acquire the lock. +    lock->Lock(); +} + +void KLightConditionVariable::Broadcast() { +    KScopedSchedulerLock lk(kernel); + +    // Signal all threads. +    for (auto it = wait_list.begin(); it != wait_list.end(); it = wait_list.erase(it)) { +        it->EndWait(ResultSuccess); +    } +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h index fb0ad783a..65d3bc3e1 100644 --- a/src/core/hle/kernel/k_light_condition_variable.h +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -1,73 +1,25 @@ -// Copyright 2020 yuzu Emulator Project +// Copyright 2021 yuzu Emulator Project  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. -// This file references various implementation details from Atmosphere, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. -  #pragma once  #include "common/common_types.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" -#include "core/hle/kernel/time_manager.h" +#include "core/hle/kernel/k_thread.h"  namespace Kernel { +  class KernelCore; +class KLightLock;  class KLightConditionVariable {  public:      explicit KLightConditionVariable(KernelCore& kernel_) : kernel{kernel_} {} -    void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true) { -        WaitImpl(lock, timeout, allow_terminating_thread); -    } - -    void Broadcast() { -        KScopedSchedulerLock lk{kernel}; - -        // Signal all threads. -        for (auto& thread : wait_list) { -            thread.SetState(ThreadState::Runnable); -        } -    } +    void Wait(KLightLock* lock, s64 timeout = -1, bool allow_terminating_thread = true); +    void Broadcast();  private: -    void WaitImpl(KLightLock* lock, s64 timeout, bool allow_terminating_thread) { -        KThread* owner = GetCurrentThreadPointer(kernel); - -        // Sleep the thread. -        { -            KScopedSchedulerLockAndSleep lk{kernel, owner, timeout}; - -            if (!allow_terminating_thread && owner->IsTerminationRequested()) { -                lk.CancelSleep(); -                return; -            } - -            lock->Unlock(); - -            // Set the thread as waiting. -            GetCurrentThread(kernel).SetState(ThreadState::Waiting); - -            // Add the thread to the queue. -            wait_list.push_back(GetCurrentThread(kernel)); -        } - -        // Remove the thread from the wait list. -        { -            KScopedSchedulerLock sl{kernel}; - -            wait_list.erase(wait_list.iterator_to(GetCurrentThread(kernel))); -        } - -        // Cancel the task that the sleep setup. -        kernel.TimeManager().UnscheduleTimeEvent(owner); - -        // Re-acquire the lock. -        lock->Lock(); -    } -      KernelCore& kernel;      KThread::WaiterList wait_list{};  }; | 
