diff options
Diffstat (limited to 'src/core/hle/kernel/k_light_condition_variable.h')
-rw-r--r-- | src/core/hle/kernel/k_light_condition_variable.h | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_light_condition_variable.h b/src/core/hle/kernel/k_light_condition_variable.h new file mode 100644 index 000000000..362d0db28 --- /dev/null +++ b/src/core/hle/kernel/k_light_condition_variable.h @@ -0,0 +1,57 @@ +// Copyright 2020 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/k_thread_queue.h" +#include "core/hle/kernel/time_manager.h" + +namespace Kernel { +class KernelCore; + +class KLightConditionVariable { +public: + explicit KLightConditionVariable(KernelCore& kernel) : thread_queue(kernel), kernel(kernel) {} + + void Wait(KLightLock* lock, s64 timeout = -1) { + WaitImpl(lock, timeout); + lock->Lock(); + } + + void Broadcast() { + KScopedSchedulerLock lk{kernel}; + while (thread_queue.WakeupFrontThread() != nullptr) { + // We want to signal all threads, and so should continue waking up until there's nothing + // to wake. + } + } + +private: + void WaitImpl(KLightLock* lock, s64 timeout) { + KThread* owner = GetCurrentThreadPointer(kernel); + + // Sleep the thread. + { + KScopedSchedulerLockAndSleep lk(kernel, owner, timeout); + lock->Unlock(); + + if (!thread_queue.SleepThread(owner)) { + lk.CancelSleep(); + return; + } + } + + // Cancel the task that the sleep setup. + kernel.TimeManager().UnscheduleTimeEvent(owner); + } + KThreadQueue thread_queue; + KernelCore& kernel; +}; +} // namespace Kernel |