mirror of
				https://github.com/Atmosphere-NX/Atmosphere.git
				synced 2025-11-03 20:41:17 +01:00 
			
		
		
		
	* result: try out some experimental shenanigans * result: sketch out some more shenanigans * result: see what it looks like to convert kernel to use result conds instead of guards * make rest of kernel use experimental new macro-ing
		
			
				
	
	
		
			107 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (c) Atmosphère-NX
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms and conditions of the GNU General Public License,
 | 
						|
 * version 2, as published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope it will be useful, but WITHOUT
 | 
						|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
						|
 * more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License
 | 
						|
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
						|
 */
 | 
						|
#include <mesosphere.hpp>
 | 
						|
 | 
						|
namespace ams::kern::svc {
 | 
						|
 | 
						|
    /* =============================    Common    ============================= */
 | 
						|
 | 
						|
    namespace {
 | 
						|
 | 
						|
        constexpr bool IsKernelAddress(uintptr_t address) {
 | 
						|
            return KernelVirtualAddressSpaceBase <= address && address < KernelVirtualAddressSpaceEnd;
 | 
						|
        }
 | 
						|
 | 
						|
        constexpr bool IsValidSignalType(ams::svc::SignalType type) {
 | 
						|
            switch (type) {
 | 
						|
                case ams::svc::SignalType_Signal:
 | 
						|
                case ams::svc::SignalType_SignalAndIncrementIfEqual:
 | 
						|
                case ams::svc::SignalType_SignalAndModifyByWaitingCountIfEqual:
 | 
						|
                    return true;
 | 
						|
                default:
 | 
						|
                    return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        constexpr bool IsValidArbitrationType(ams::svc::ArbitrationType type) {
 | 
						|
            switch (type) {
 | 
						|
                case ams::svc::ArbitrationType_WaitIfLessThan:
 | 
						|
                case ams::svc::ArbitrationType_DecrementAndWaitIfLessThan:
 | 
						|
                case ams::svc::ArbitrationType_WaitIfEqual:
 | 
						|
                    return true;
 | 
						|
                default:
 | 
						|
                    return false;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        Result WaitForAddress(uintptr_t address, ams::svc::ArbitrationType arb_type, int32_t value, int64_t timeout_ns) {
 | 
						|
            /* Validate input. */
 | 
						|
            R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)),     svc::ResultInvalidCurrentMemory());
 | 
						|
            R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress());
 | 
						|
            R_UNLESS(IsValidArbitrationType(arb_type),          svc::ResultInvalidEnumValue());
 | 
						|
 | 
						|
            /* Convert timeout from nanoseconds to ticks. */
 | 
						|
            s64 timeout;
 | 
						|
            if (timeout_ns > 0) {
 | 
						|
                const ams::svc::Tick offset_tick(TimeSpan::FromNanoSeconds(timeout_ns));
 | 
						|
                if (AMS_LIKELY(offset_tick > 0)) {
 | 
						|
                    timeout = KHardwareTimer::GetTick() + offset_tick + 2;
 | 
						|
                    if (AMS_UNLIKELY(timeout <= 0)) {
 | 
						|
                        timeout = std::numeric_limits<s64>::max();
 | 
						|
                    }
 | 
						|
                } else {
 | 
						|
                    timeout = std::numeric_limits<s64>::max();
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                timeout = timeout_ns;
 | 
						|
            }
 | 
						|
 | 
						|
            R_RETURN(GetCurrentProcess().WaitAddressArbiter(address, arb_type, value, timeout));
 | 
						|
        }
 | 
						|
 | 
						|
        Result SignalToAddress(uintptr_t address, ams::svc::SignalType signal_type, int32_t value, int32_t count) {
 | 
						|
            /* Validate input. */
 | 
						|
            R_UNLESS(AMS_LIKELY(!IsKernelAddress(address)),     svc::ResultInvalidCurrentMemory());
 | 
						|
            R_UNLESS(util::IsAligned(address, sizeof(int32_t)), svc::ResultInvalidAddress());
 | 
						|
            R_UNLESS(IsValidSignalType(signal_type),            svc::ResultInvalidEnumValue());
 | 
						|
 | 
						|
            R_RETURN(GetCurrentProcess().SignalAddressArbiter(address, signal_type, value, count));
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /* =============================    64 ABI    ============================= */
 | 
						|
 | 
						|
    Result WaitForAddress64(ams::svc::Address address, ams::svc::ArbitrationType arb_type, int32_t value, int64_t timeout_ns) {
 | 
						|
        R_RETURN(WaitForAddress(address, arb_type, value, timeout_ns));
 | 
						|
    }
 | 
						|
 | 
						|
    Result SignalToAddress64(ams::svc::Address address, ams::svc::SignalType signal_type, int32_t value, int32_t count) {
 | 
						|
        R_RETURN(SignalToAddress(address, signal_type, value, count));
 | 
						|
    }
 | 
						|
 | 
						|
    /* ============================= 64From32 ABI ============================= */
 | 
						|
 | 
						|
    Result WaitForAddress64From32(ams::svc::Address address, ams::svc::ArbitrationType arb_type, int32_t value, int64_t timeout_ns) {
 | 
						|
        R_RETURN(WaitForAddress(address, arb_type, value, timeout_ns));
 | 
						|
    }
 | 
						|
 | 
						|
    Result SignalToAddress64From32(ams::svc::Address address, ams::svc::SignalType signal_type, int32_t value, int32_t count) {
 | 
						|
        R_RETURN(SignalToAddress(address, signal_type, value, count));
 | 
						|
    }
 | 
						|
 | 
						|
}
 |