diff options
author | bunnei <bunneidev@gmail.com> | 2018-01-09 03:41:37 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2018-01-09 03:41:37 +0100 |
commit | 423679983259948c203e546887445a59b64fc32f (patch) | |
tree | d359c88bb9347677025a9f0e64a08e0ab1733a4a /src/core/hle/kernel/condition_variable.cpp | |
parent | mutex: Remove unused call to VerifyGuestState. (diff) | |
download | yuzu-423679983259948c203e546887445a59b64fc32f.tar yuzu-423679983259948c203e546887445a59b64fc32f.tar.gz yuzu-423679983259948c203e546887445a59b64fc32f.tar.bz2 yuzu-423679983259948c203e546887445a59b64fc32f.tar.lz yuzu-423679983259948c203e546887445a59b64fc32f.tar.xz yuzu-423679983259948c203e546887445a59b64fc32f.tar.zst yuzu-423679983259948c203e546887445a59b64fc32f.zip |
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 |