diff options
author | Mai <mai.iam2048@gmail.com> | 2023-02-05 08:26:52 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-05 08:26:52 +0100 |
commit | 037300014385d7dd25029d7aac188f325f1e5bc3 (patch) | |
tree | be79f36453a4735088d9230e02f426792077eeb4 /src/core/hle/kernel/svc/svc_condition_variable.cpp | |
parent | Merge pull request #9720 from SoRadGaming/discordPresenceUpdate (diff) | |
parent | kernel/svc: Split implementations into separate files (diff) | |
download | yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar.gz yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar.bz2 yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar.lz yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar.xz yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.tar.zst yuzu-037300014385d7dd25029d7aac188f325f1e5bc3.zip |
Diffstat (limited to 'src/core/hle/kernel/svc/svc_condition_variable.cpp')
-rw-r--r-- | src/core/hle/kernel/svc/svc_condition_variable.cpp | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc/svc_condition_variable.cpp b/src/core/hle/kernel/svc/svc_condition_variable.cpp new file mode 100644 index 000000000..d6cfc87c5 --- /dev/null +++ b/src/core/hle/kernel/svc/svc_condition_variable.cpp @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/kernel/k_memory_layout.h" +#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/svc.h" +#include "core/hle/kernel/svc_results.h" + +namespace Kernel::Svc { + +/// Wait process wide key atomic +Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, u32 tag, + s64 timeout_ns) { + LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address, + cv_key, tag, timeout_ns); + + // Validate input. + if (IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(s32))) { + LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address); + return ResultInvalidAddress; + } + + // Convert timeout from nanoseconds to ticks. + s64 timeout{}; + if (timeout_ns > 0) { + const s64 offset_tick(timeout_ns); + if (offset_tick > 0) { + timeout = offset_tick + 2; + if (timeout <= 0) { + timeout = std::numeric_limits<s64>::max(); + } + } else { + timeout = std::numeric_limits<s64>::max(); + } + } else { + timeout = timeout_ns; + } + + // Wait on the condition variable. + return system.Kernel().CurrentProcess()->WaitConditionVariable( + address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout); +} + +Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag, + u32 timeout_ns_low, u32 timeout_ns_high) { + const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32)); + return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns); +} + +/// Signal process wide key +void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) { + LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count); + + // Signal the condition variable. + return system.Kernel().CurrentProcess()->SignalConditionVariable( + Common::AlignDown(cv_key, sizeof(u32)), count); +} + +void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count) { + SignalProcessWideKey(system, cv_key, count); +} + +} // namespace Kernel::Svc |