// 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::max(); } } else { timeout = std::numeric_limits::max(); } } else { timeout = timeout_ns; } // Wait on the condition variable. return GetCurrentProcess(system.Kernel()) .WaitConditionVariable(address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout); } /// 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 GetCurrentProcess(system.Kernel()) .SignalConditionVariable(Common::AlignDown(cv_key, sizeof(u32)), count); } Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key, uint32_t tag, int64_t timeout_ns) { R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns)); } void SignalProcessWideKey64(Core::System& system, uint64_t cv_key, int32_t count) { SignalProcessWideKey(system, cv_key, count); } Result WaitProcessWideKeyAtomic64From32(Core::System& system, uint32_t address, uint32_t cv_key, uint32_t tag, int64_t timeout_ns) { R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns)); } void SignalProcessWideKey64From32(Core::System& system, uint32_t cv_key, int32_t count) { SignalProcessWideKey(system, cv_key, count); } } // namespace Kernel::Svc