summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2018-06-22 12:08:39 -0400
committerGravatar GitHub2018-06-22 12:08:39 -0400
commit6d7941042bd8badcd8e93521b40cbbc29215351e (patch)
treef4b72f5d717e1fffe784b1f4100fe01177b6b02a /src/core/hle/kernel/svc.cpp
parentMerge pull request #581 from mailwl/empty-buf-skip (diff)
parentKernel/Arbiters: Fix casts, cleanup comments/magic numbers (diff)
downloadyuzu-6d7941042bd8badcd8e93521b40cbbc29215351e.tar.gz
yuzu-6d7941042bd8badcd8e93521b40cbbc29215351e.tar.xz
yuzu-6d7941042bd8badcd8e93521b40cbbc29215351e.zip
Merge pull request #579 from SciresM/master
svc: Fully implement svcSignalToAddress and svcWaitForAddress
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp59
1 files changed, 56 insertions, 3 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 69ba7b777..1a36e0d02 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -11,6 +11,7 @@
11#include "common/string_util.h" 11#include "common/string_util.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_timing.h" 13#include "core/core_timing.h"
14#include "core/hle/kernel/address_arbiter.h"
14#include "core/hle/kernel/client_port.h" 15#include "core/hle/kernel/client_port.h"
15#include "core/hle/kernel/client_session.h" 16#include "core/hle/kernel/client_session.h"
16#include "core/hle/kernel/event.h" 17#include "core/hle/kernel/event.h"
@@ -580,7 +581,7 @@ static void SleepThread(s64 nanoseconds) {
580 Core::System::GetInstance().PrepareReschedule(); 581 Core::System::GetInstance().PrepareReschedule();
581} 582}
582 583
583/// Signal process wide key atomic 584/// Wait process wide key atomic
584static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr, 585static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
585 Handle thread_handle, s64 nano_seconds) { 586 Handle thread_handle, s64 nano_seconds) {
586 NGLOG_TRACE( 587 NGLOG_TRACE(
@@ -689,6 +690,58 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
689 return RESULT_SUCCESS; 690 return RESULT_SUCCESS;
690} 691}
691 692
693// Wait for an address (via Address Arbiter)
694static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout) {
695 NGLOG_WARNING(Kernel_SVC, "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, timeout={}",
696 address, type, value, timeout);
697 // If the passed address is a kernel virtual address, return invalid memory state.
698 if (Memory::IsKernelVirtualAddress(address)) {
699 return ERR_INVALID_ADDRESS_STATE;
700 }
701 // If the address is not properly aligned to 4 bytes, return invalid address.
702 if (address % sizeof(u32) != 0) {
703 return ERR_INVALID_ADDRESS;
704 }
705
706 switch (static_cast<AddressArbiter::ArbitrationType>(type)) {
707 case AddressArbiter::ArbitrationType::WaitIfLessThan:
708 return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false);
709 case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan:
710 return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true);
711 case AddressArbiter::ArbitrationType::WaitIfEqual:
712 return AddressArbiter::WaitForAddressIfEqual(address, value, timeout);
713 default:
714 return ERR_INVALID_ENUM_VALUE;
715 }
716}
717
718// Signals to an address (via Address Arbiter)
719static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to_wake) {
720 NGLOG_WARNING(Kernel_SVC,
721 "called, address=0x{:X}, type=0x{:X}, value=0x{:X}, num_to_wake=0x{:X}", address,
722 type, value, num_to_wake);
723 // If the passed address is a kernel virtual address, return invalid memory state.
724 if (Memory::IsKernelVirtualAddress(address)) {
725 return ERR_INVALID_ADDRESS_STATE;
726 }
727 // If the address is not properly aligned to 4 bytes, return invalid address.
728 if (address % sizeof(u32) != 0) {
729 return ERR_INVALID_ADDRESS;
730 }
731
732 switch (static_cast<AddressArbiter::SignalType>(type)) {
733 case AddressArbiter::SignalType::Signal:
734 return AddressArbiter::SignalToAddress(address, num_to_wake);
735 case AddressArbiter::SignalType::IncrementAndSignalIfEqual:
736 return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake);
737 case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual:
738 return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value,
739 num_to_wake);
740 default:
741 return ERR_INVALID_ENUM_VALUE;
742 }
743}
744
692/// This returns the total CPU ticks elapsed since the CPU was powered-on 745/// This returns the total CPU ticks elapsed since the CPU was powered-on
693static u64 GetSystemTick() { 746static u64 GetSystemTick() {
694 const u64 result{CoreTiming::GetTicks()}; 747 const u64 result{CoreTiming::GetTicks()};
@@ -861,8 +914,8 @@ static const FunctionDef SVC_Table[] = {
861 {0x31, nullptr, "GetResourceLimitCurrentValue"}, 914 {0x31, nullptr, "GetResourceLimitCurrentValue"},
862 {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"}, 915 {0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
863 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"}, 916 {0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
864 {0x34, nullptr, "WaitForAddress"}, 917 {0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
865 {0x35, nullptr, "SignalToAddress"}, 918 {0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
866 {0x36, nullptr, "Unknown"}, 919 {0x36, nullptr, "Unknown"},
867 {0x37, nullptr, "Unknown"}, 920 {0x37, nullptr, "Unknown"},
868 {0x38, nullptr, "Unknown"}, 921 {0x38, nullptr, "Unknown"},