summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2020-12-30 01:14:02 -0800
committerGravatar bunnei2021-01-11 14:23:16 -0800
commit912dd501465ffaabd149cc3532839e346982b337 (patch)
tree54f650b18baf040bf9a0555e386989ef2189c223 /src/core/hle/kernel/svc.cpp
parentcore: hle: kernel: Update KAddressArbiter. (diff)
downloadyuzu-912dd501465ffaabd149cc3532839e346982b337.tar.gz
yuzu-912dd501465ffaabd149cc3532839e346982b337.tar.xz
yuzu-912dd501465ffaabd149cc3532839e346982b337.zip
core: hle: Integrate new KConditionVariable and KAddressArbiter implementations.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp364
1 files changed, 127 insertions, 237 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 304b8727d..99bb4ea20 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -10,6 +10,7 @@
10 10
11#include "common/alignment.h" 11#include "common/alignment.h"
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/common_funcs.h"
13#include "common/fiber.h" 14#include "common/fiber.h"
14#include "common/logging/log.h" 15#include "common/logging/log.h"
15#include "common/microprofile.h" 16#include "common/microprofile.h"
@@ -19,24 +20,26 @@
19#include "core/core_timing.h" 20#include "core/core_timing.h"
20#include "core/core_timing_util.h" 21#include "core/core_timing_util.h"
21#include "core/cpu_manager.h" 22#include "core/cpu_manager.h"
22#include "core/hle/kernel/address_arbiter.h"
23#include "core/hle/kernel/client_port.h" 23#include "core/hle/kernel/client_port.h"
24#include "core/hle/kernel/client_session.h" 24#include "core/hle/kernel/client_session.h"
25#include "core/hle/kernel/errors.h" 25#include "core/hle/kernel/errors.h"
26#include "core/hle/kernel/handle_table.h" 26#include "core/hle/kernel/handle_table.h"
27#include "core/hle/kernel/k_address_arbiter.h"
28#include "core/hle/kernel/k_condition_variable.h"
27#include "core/hle/kernel/k_scheduler.h" 29#include "core/hle/kernel/k_scheduler.h"
28#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 30#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
29#include "core/hle/kernel/k_synchronization_object.h" 31#include "core/hle/kernel/k_synchronization_object.h"
30#include "core/hle/kernel/kernel.h" 32#include "core/hle/kernel/kernel.h"
31#include "core/hle/kernel/memory/memory_block.h" 33#include "core/hle/kernel/memory/memory_block.h"
34#include "core/hle/kernel/memory/memory_layout.h"
32#include "core/hle/kernel/memory/page_table.h" 35#include "core/hle/kernel/memory/page_table.h"
33#include "core/hle/kernel/mutex.h"
34#include "core/hle/kernel/physical_core.h" 36#include "core/hle/kernel/physical_core.h"
35#include "core/hle/kernel/process.h" 37#include "core/hle/kernel/process.h"
36#include "core/hle/kernel/readable_event.h" 38#include "core/hle/kernel/readable_event.h"
37#include "core/hle/kernel/resource_limit.h" 39#include "core/hle/kernel/resource_limit.h"
38#include "core/hle/kernel/shared_memory.h" 40#include "core/hle/kernel/shared_memory.h"
39#include "core/hle/kernel/svc.h" 41#include "core/hle/kernel/svc.h"
42#include "core/hle/kernel/svc_results.h"
40#include "core/hle/kernel/svc_types.h" 43#include "core/hle/kernel/svc_types.h"
41#include "core/hle/kernel/svc_wrap.h" 44#include "core/hle/kernel/svc_wrap.h"
42#include "core/hle/kernel/thread.h" 45#include "core/hle/kernel/thread.h"
@@ -347,12 +350,6 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
347 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 350 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
348 } 351 }
349 352
350 Handle event_handle = thread->GetHLETimeEvent();
351 if (event_handle != InvalidHandle) {
352 auto& time_manager = kernel.TimeManager();
353 time_manager.UnscheduleTimeEvent(event_handle);
354 }
355
356 return thread->GetSignalingResult(); 353 return thread->GetSignalingResult();
357} 354}
358 355
@@ -491,56 +488,37 @@ static ResultCode CancelSynchronization32(Core::System& system, Handle thread_ha
491 return CancelSynchronization(system, thread_handle); 488 return CancelSynchronization(system, thread_handle);
492} 489}
493 490
494/// Attempts to locks a mutex, creating it if it does not already exist 491/// Attempts to locks a mutex
495static ResultCode ArbitrateLock(Core::System& system, Handle holding_thread_handle, 492static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address,
496 VAddr mutex_addr, Handle requesting_thread_handle) { 493 u32 tag) {
497 LOG_TRACE(Kernel_SVC, 494 LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address=0x{:X}, tag=0x{:08X}",
498 "called holding_thread_handle=0x{:08X}, mutex_addr=0x{:X}, " 495 thread_handle, address, tag);
499 "requesting_current_thread_handle=0x{:08X}",
500 holding_thread_handle, mutex_addr, requesting_thread_handle);
501
502 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) {
503 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}",
504 mutex_addr);
505 return ERR_INVALID_ADDRESS_STATE;
506 }
507 496
508 if (!Common::IsWordAligned(mutex_addr)) { 497 // Validate the input address.
509 LOG_ERROR(Kernel_SVC, "Mutex Address is not word aligned, mutex_addr={:016X}", mutex_addr); 498 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
510 return ERR_INVALID_ADDRESS; 499 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
511 }
512 500
513 auto* const current_process = system.Kernel().CurrentProcess(); 501 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
514 return current_process->GetMutex().TryAcquire(mutex_addr, holding_thread_handle,
515 requesting_thread_handle);
516} 502}
517 503
518static ResultCode ArbitrateLock32(Core::System& system, Handle holding_thread_handle, 504static ResultCode ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address,
519 u32 mutex_addr, Handle requesting_thread_handle) { 505 u32 tag) {
520 return ArbitrateLock(system, holding_thread_handle, mutex_addr, requesting_thread_handle); 506 return ArbitrateLock(system, thread_handle, address, tag);
521} 507}
522 508
523/// Unlock a mutex 509/// Unlock a mutex
524static ResultCode ArbitrateUnlock(Core::System& system, VAddr mutex_addr) { 510static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
525 LOG_TRACE(Kernel_SVC, "called mutex_addr=0x{:X}", mutex_addr); 511 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
526 512
527 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) { 513 // Validate the input address.
528 LOG_ERROR(Kernel_SVC, "Mutex Address is a kernel virtual address, mutex_addr={:016X}", 514 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
529 mutex_addr); 515 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress);
530 return ERR_INVALID_ADDRESS_STATE;
531 }
532 516
533 if (!Common::IsWordAligned(mutex_addr)) { 517 return system.Kernel().CurrentProcess()->SignalToAddress(address);
534 LOG_ERROR(Kernel_SVC, "Mutex Address is not word aligned, mutex_addr={:016X}", mutex_addr);
535 return ERR_INVALID_ADDRESS;
536 }
537
538 auto* const current_process = system.Kernel().CurrentProcess();
539 return current_process->GetMutex().Release(mutex_addr);
540} 518}
541 519
542static ResultCode ArbitrateUnlock32(Core::System& system, u32 mutex_addr) { 520static ResultCode ArbitrateUnlock32(Core::System& system, u32 address) {
543 return ArbitrateUnlock(system, mutex_addr); 521 return ArbitrateUnlock(system, address);
544} 522}
545 523
546enum class BreakType : u32 { 524enum class BreakType : u32 {
@@ -1167,7 +1145,7 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
1167 return ERR_INVALID_HANDLE; 1145 return ERR_INVALID_HANDLE;
1168 } 1146 }
1169 1147
1170 thread->SetPriority(priority); 1148 thread->SetBasePriority(priority);
1171 1149
1172 return RESULT_SUCCESS; 1150 return RESULT_SUCCESS;
1173} 1151}
@@ -1607,223 +1585,135 @@ static void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanosec
1607} 1585}
1608 1586
1609/// Wait process wide key atomic 1587/// Wait process wide key atomic
1610static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_addr, 1588static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key,
1611 VAddr condition_variable_addr, Handle thread_handle, 1589 u32 tag, s64 timeout_ns) {
1612 s64 nano_seconds) { 1590 LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address,
1613 LOG_TRACE( 1591 cv_key, tag, timeout_ns);
1614 Kernel_SVC, 1592
1615 "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}", 1593 // Validate input.
1616 mutex_addr, condition_variable_addr, thread_handle, nano_seconds); 1594 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
1617 1595 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
1618 if (Core::Memory::IsKernelVirtualAddress(mutex_addr)) { 1596
1619 LOG_ERROR( 1597 // Convert timeout from nanoseconds to ticks.
1620 Kernel_SVC, 1598 s64 timeout{};
1621 "Given mutex address must not be within the kernel address space. address=0x{:016X}", 1599 if (timeout_ns > 0) {
1622 mutex_addr); 1600 const s64 offset_tick(timeout_ns);
1623 return ERR_INVALID_ADDRESS_STATE; 1601 if (offset_tick > 0) {
1624 } 1602 timeout = offset_tick + 2;
1625 1603 if (timeout <= 0) {
1626 if (!Common::IsWordAligned(mutex_addr)) { 1604 timeout = std::numeric_limits<s64>::max();
1627 LOG_ERROR(Kernel_SVC, "Given mutex address must be word-aligned. address=0x{:016X}", 1605 }
1628 mutex_addr); 1606 } else {
1629 return ERR_INVALID_ADDRESS; 1607 timeout = std::numeric_limits<s64>::max();
1630 }
1631
1632 ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4));
1633 auto& kernel = system.Kernel();
1634 Handle event_handle;
1635 Thread* current_thread = kernel.CurrentScheduler()->GetCurrentThread();
1636 auto* const current_process = kernel.CurrentProcess();
1637 {
1638 KScopedSchedulerLockAndSleep lock(kernel, event_handle, current_thread, nano_seconds);
1639 const auto& handle_table = current_process->GetHandleTable();
1640 std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle);
1641 ASSERT(thread);
1642
1643 current_thread->SetSynchronizationResults(nullptr, RESULT_TIMEOUT);
1644
1645 if (thread->IsTerminationRequested()) {
1646 lock.CancelSleep();
1647 return ERR_THREAD_TERMINATING;
1648 }
1649
1650 const auto release_result = current_process->GetMutex().Release(mutex_addr);
1651 if (release_result.IsError()) {
1652 lock.CancelSleep();
1653 return release_result;
1654 }
1655
1656 if (nano_seconds == 0) {
1657 lock.CancelSleep();
1658 return RESULT_TIMEOUT;
1659 }
1660
1661 current_thread->SetCondVarWaitAddress(condition_variable_addr);
1662 current_thread->SetMutexWaitAddress(mutex_addr);
1663 current_thread->SetWaitHandle(thread_handle);
1664 current_thread->SetState(ThreadState::Waiting);
1665 current_thread->SetWaitingCondVar(true);
1666 current_process->InsertConditionVariableThread(SharedFrom(current_thread));
1667 }
1668
1669 if (event_handle != InvalidHandle) {
1670 auto& time_manager = kernel.TimeManager();
1671 time_manager.UnscheduleTimeEvent(event_handle);
1672 }
1673
1674 {
1675 KScopedSchedulerLock lock(kernel);
1676
1677 auto* owner = current_thread->GetLockOwner();
1678 if (owner != nullptr) {
1679 owner->RemoveMutexWaiter(SharedFrom(current_thread));
1680 } 1608 }
1681 1609 } else {
1682 current_process->RemoveConditionVariableThread(SharedFrom(current_thread)); 1610 timeout = timeout_ns;
1683 } 1611 }
1684 // Note: Deliberately don't attempt to inherit the lock owner's priority.
1685 1612
1686 return current_thread->GetSignalingResult(); 1613 // Wait on the condition variable.
1614 return system.Kernel().CurrentProcess()->WaitConditionVariable(
1615 address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
1687} 1616}
1688 1617
1689static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 mutex_addr, 1618static ResultCode WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
1690 u32 condition_variable_addr, Handle thread_handle, 1619 u32 timeout_ns_low, u32 timeout_ns_high) {
1691 u32 nanoseconds_low, u32 nanoseconds_high) { 1620 const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
1692 const auto nanoseconds = static_cast<s64>(nanoseconds_low | (u64{nanoseconds_high} << 32)); 1621 return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns);
1693 return WaitProcessWideKeyAtomic(system, mutex_addr, condition_variable_addr, thread_handle,
1694 nanoseconds);
1695} 1622}
1696 1623
1697/// Signal process wide key 1624/// Signal process wide key
1698static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_addr, s32 target) { 1625static void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) {
1699 LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}", 1626 LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count);
1700 condition_variable_addr, target); 1627
1628 // Signal the condition variable.
1629 return system.Kernel().CurrentProcess()->SignalConditionVariable(
1630 Common::AlignDown(cv_key, sizeof(u32)), count);
1631}
1701 1632
1702 ASSERT(condition_variable_addr == Common::AlignDown(condition_variable_addr, 4)); 1633static void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count) {
1634 SignalProcessWideKey(system, cv_key, count);
1635}
1703 1636
1704 // Retrieve a list of all threads that are waiting for this condition variable. 1637namespace {
1705 auto& kernel = system.Kernel();
1706 KScopedSchedulerLock lock(kernel);
1707 auto* const current_process = kernel.CurrentProcess();
1708 std::vector<std::shared_ptr<Thread>> waiting_threads =
1709 current_process->GetConditionVariableThreads(condition_variable_addr);
1710
1711 // Only process up to 'target' threads, unless 'target' is less equal 0, in which case process
1712 // them all.
1713 std::size_t last = waiting_threads.size();
1714 if (target > 0) {
1715 last = std::min(waiting_threads.size(), static_cast<std::size_t>(target));
1716 }
1717 for (std::size_t index = 0; index < last; ++index) {
1718 auto& thread = waiting_threads[index];
1719
1720 ASSERT(thread->GetCondVarWaitAddress() == condition_variable_addr);
1721
1722 // liberate Cond Var Thread.
1723 current_process->RemoveConditionVariableThread(thread);
1724
1725 const std::size_t current_core = system.CurrentCoreIndex();
1726 auto& monitor = system.Monitor();
1727
1728 // Atomically read the value of the mutex.
1729 u32 mutex_val = 0;
1730 u32 update_val = 0;
1731 const VAddr mutex_address = thread->GetMutexWaitAddress();
1732 do {
1733 // If the mutex is not yet acquired, acquire it.
1734 mutex_val = monitor.ExclusiveRead32(current_core, mutex_address);
1735
1736 if (mutex_val != 0) {
1737 update_val = mutex_val | Mutex::MutexHasWaitersFlag;
1738 } else {
1739 update_val = thread->GetWaitHandle();
1740 }
1741 } while (!monitor.ExclusiveWrite32(current_core, mutex_address, update_val));
1742 monitor.ClearExclusive();
1743 if (mutex_val == 0) {
1744 // We were able to acquire the mutex, resume this thread.
1745 auto* const lock_owner = thread->GetLockOwner();
1746 if (lock_owner != nullptr) {
1747 lock_owner->RemoveMutexWaiter(thread);
1748 }
1749 1638
1750 thread->SetLockOwner(nullptr); 1639constexpr bool IsValidSignalType(Svc::SignalType type) {
1751 thread->SetSynchronizationResults(nullptr, RESULT_SUCCESS); 1640 switch (type) {
1752 thread->Wakeup(); 1641 case Svc::SignalType::Signal:
1753 } else { 1642 case Svc::SignalType::SignalAndIncrementIfEqual:
1754 // The mutex is already owned by some other thread, make this thread wait on it. 1643 case Svc::SignalType::SignalAndModifyByWaitingCountIfEqual:
1755 const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); 1644 return true;
1756 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1645 default:
1757 auto owner = handle_table.Get<Thread>(owner_handle); 1646 return false;
1758 ASSERT(owner);
1759 thread->SetWaitingCondVar(false);
1760
1761 owner->AddMutexWaiter(thread);
1762 }
1763 } 1647 }
1764} 1648}
1765 1649
1766static void SignalProcessWideKey32(Core::System& system, u32 condition_variable_addr, s32 target) { 1650constexpr bool IsValidArbitrationType(Svc::ArbitrationType type) {
1767 SignalProcessWideKey(system, condition_variable_addr, target); 1651 switch (type) {
1652 case Svc::ArbitrationType::WaitIfLessThan:
1653 case Svc::ArbitrationType::DecrementAndWaitIfLessThan:
1654 case Svc::ArbitrationType::WaitIfEqual:
1655 return true;
1656 default:
1657 return false;
1658 }
1768} 1659}
1769 1660
1770// Wait for an address (via Address Arbiter) 1661} // namespace
1771static ResultCode WaitForAddress(Core::System& system, VAddr address, u32 type, s32 value,
1772 s64 timeout) {
1773 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}", address,
1774 type, value, timeout);
1775
1776 // If the passed address is a kernel virtual address, return invalid memory state.
1777 if (Core::Memory::IsKernelVirtualAddress(address)) {
1778 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
1779 return ERR_INVALID_ADDRESS_STATE;
1780 }
1781 1662
1782 // If the address is not properly aligned to 4 bytes, return invalid address. 1663// Wait for an address (via Address Arbiter)
1783 if (!Common::IsWordAligned(address)) { 1664static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::ArbitrationType arb_type,
1784 LOG_ERROR(Kernel_SVC, "Address is not word aligned, address={:016X}", address); 1665 s32 value, s64 timeout_ns) {
1785 return ERR_INVALID_ADDRESS; 1666 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}",
1667 address, arb_type, value, timeout_ns);
1668
1669 // Validate input.
1670 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
1671 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress);
1672 R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue);
1673
1674 // Convert timeout from nanoseconds to ticks.
1675 s64 timeout{};
1676 if (timeout_ns > 0) {
1677 const s64 offset_tick(timeout_ns);
1678 if (offset_tick > 0) {
1679 timeout = offset_tick + 2;
1680 if (timeout <= 0) {
1681 timeout = std::numeric_limits<s64>::max();
1682 }
1683 } else {
1684 timeout = std::numeric_limits<s64>::max();
1685 }
1686 } else {
1687 timeout = timeout_ns;
1786 } 1688 }
1787 1689
1788 const auto arbitration_type = static_cast<AddressArbiter::ArbitrationType>(type); 1690 return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout);
1789 auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter();
1790 const ResultCode result =
1791 address_arbiter.WaitForAddress(address, arbitration_type, value, timeout);
1792 return result;
1793} 1691}
1794 1692
1795static ResultCode WaitForAddress32(Core::System& system, u32 address, u32 type, s32 value, 1693static ResultCode WaitForAddress32(Core::System& system, u32 address, Svc::ArbitrationType arb_type,
1796 u32 timeout_low, u32 timeout_high) { 1694 s32 value, u32 timeout_ns_low, u32 timeout_ns_high) {
1797 const auto timeout = static_cast<s64>(timeout_low | (u64{timeout_high} << 32)); 1695 const auto timeout = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
1798 return WaitForAddress(system, address, type, value, timeout); 1696 return WaitForAddress(system, address, arb_type, value, timeout);
1799} 1697}
1800 1698
1801// Signals to an address (via Address Arbiter) 1699// Signals to an address (via Address Arbiter)
1802static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, s32 value, 1700static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::SignalType signal_type,
1803 s32 num_to_wake) { 1701 s32 value, s32 count) {
1804 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", 1702 LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}",
1805 address, type, value, num_to_wake); 1703 address, signal_type, value, count);
1806
1807 // If the passed address is a kernel virtual address, return invalid memory state.
1808 if (Core::Memory::IsKernelVirtualAddress(address)) {
1809 LOG_ERROR(Kernel_SVC, "Address is a kernel virtual address, address={:016X}", address);
1810 return ERR_INVALID_ADDRESS_STATE;
1811 }
1812 1704
1813 // If the address is not properly aligned to 4 bytes, return invalid address. 1705 // Validate input.
1814 if (!Common::IsWordAligned(address)) { 1706 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory);
1815 LOG_ERROR(Kernel_SVC, "Address is not word aligned, address={:016X}", address); 1707 R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress);
1816 return ERR_INVALID_ADDRESS; 1708 R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue);
1817 }
1818 1709
1819 const auto signal_type = static_cast<AddressArbiter::SignalType>(type); 1710 return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
1820 auto& address_arbiter = system.Kernel().CurrentProcess()->GetAddressArbiter(); 1711 count);
1821 return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake);
1822} 1712}
1823 1713
1824static ResultCode SignalToAddress32(Core::System& system, u32 address, u32 type, s32 value, 1714static ResultCode SignalToAddress32(Core::System& system, u32 address, Svc::SignalType signal_type,
1825 s32 num_to_wake) { 1715 s32 value, s32 count) {
1826 return SignalToAddress(system, address, type, value, num_to_wake); 1716 return SignalToAddress(system, address, signal_type, value, count);
1827} 1717}
1828 1718
1829static void KernelDebug([[maybe_unused]] Core::System& system, 1719static void KernelDebug([[maybe_unused]] Core::System& system,