diff options
Diffstat (limited to 'src/core/hle/kernel/condition_variable.cpp')
-rw-r--r-- | src/core/hle/kernel/condition_variable.cpp | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/src/core/hle/kernel/condition_variable.cpp b/src/core/hle/kernel/condition_variable.cpp new file mode 100644 index 000000000..8908aeeb6 --- /dev/null +++ b/src/core/hle/kernel/condition_variable.cpp @@ -0,0 +1,65 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "core/hle/kernel/condition_variable.h" +#include "core/hle/kernel/errors.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/object_address_table.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +ConditionVariable::ConditionVariable() {} +ConditionVariable::~ConditionVariable() {} + +ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr, + VAddr mutex_addr, + std::string name) { + SharedPtr<ConditionVariable> condition_variable(new ConditionVariable); + + condition_variable->name = std::move(name); + condition_variable->guest_addr = guest_addr; + condition_variable->mutex_addr = mutex_addr; + + // Condition variables are referenced by guest address, so track this in the kernel + g_object_address_table.Insert(guest_addr, condition_variable); + + return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable)); +} + +bool ConditionVariable::ShouldWait(Thread* thread) const { + return GetAvailableCount() <= 0; +} + +void ConditionVariable::Acquire(Thread* thread) { + if (GetAvailableCount() <= 0) + return; + + SetAvailableCount(GetAvailableCount() - 1); +} + +ResultCode ConditionVariable::Release(s32 target) { + if (target == -1) { + // When -1, wake up all waiting threads + SetAvailableCount(GetWaitingThreads().size()); + WakeupAllWaitingThreads(); + } else { + // Otherwise, wake up just a single thread + SetAvailableCount(target); + WakeupWaitingThread(GetHighestPriorityReadyThread()); + } + + return RESULT_SUCCESS; +} + +s32 ConditionVariable::GetAvailableCount() const { + return Memory::Read32(guest_addr); +} + +void ConditionVariable::SetAvailableCount(s32 value) const { + Memory::Write32(guest_addr, value); +} + +} // namespace Kernel |