From 3e922c262d26ee7c65b9372649b76895b389df37 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 17 Aug 2023 19:50:20 +0200 Subject: [PATCH] early-access version 3816 --- README.md | 2 +- src/core/hle/kernel/k_hardware_timer.h | 9 +----- src/core/hle/kernel/k_resource_limit.cpp | 11 ++++--- src/core/hle/kernel/k_resource_limit.h | 3 +- .../k_scoped_scheduler_lock_and_sleep.h | 2 +- src/core/hle/kernel/kernel.cpp | 2 +- .../hle/kernel/svc/svc_address_arbiter.cpp | 3 +- .../hle/kernel/svc/svc_condition_variable.cpp | 3 +- src/core/hle/kernel/svc/svc_ipc.cpp | 20 ++++++++++++- .../hle/kernel/svc/svc_resource_limit.cpp | 2 +- .../hle/kernel/svc/svc_synchronization.cpp | 16 ++++++++-- src/core/hle/kernel/svc/svc_thread.cpp | 29 +++++++++++++------ 12 files changed, 68 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 9a1a5ea43..91607f4ef 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3815. +This is the source code for early-access 3816. ## Legal Notice diff --git a/src/core/hle/kernel/k_hardware_timer.h b/src/core/hle/kernel/k_hardware_timer.h index 00bef6ea1..27f43cd19 100755 --- a/src/core/hle/kernel/k_hardware_timer.h +++ b/src/core/hle/kernel/k_hardware_timer.h @@ -19,13 +19,7 @@ public: void Initialize(); void Finalize(); - s64 GetCount() const { - return GetTick(); - } - - void RegisterTask(KTimerTask* task, s64 time_from_now) { - this->RegisterAbsoluteTask(task, GetTick() + time_from_now); - } + s64 GetTick() const; void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) { KScopedDisableDispatch dd{m_kernel}; @@ -42,7 +36,6 @@ private: void EnableInterrupt(s64 wakeup_time); void DisableInterrupt(); bool GetInterruptEnabled(); - s64 GetTick() const; void DoTask(); private: diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 14a71e42f..2bf0253c6 100755 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -5,6 +5,7 @@ #include "common/overflow.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/svc_results.h" @@ -15,9 +16,7 @@ KResourceLimit::KResourceLimit(KernelCore& kernel) : KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{m_kernel}, m_cond_var{m_kernel} {} KResourceLimit::~KResourceLimit() = default; -void KResourceLimit::Initialize(const Core::Timing::CoreTiming* core_timing) { - m_core_timing = core_timing; -} +void KResourceLimit::Initialize() {} void KResourceLimit::Finalize() {} @@ -86,7 +85,7 @@ Result KResourceLimit::SetLimitValue(LimitableResource which, s64 value) { } bool KResourceLimit::Reserve(LimitableResource which, s64 value) { - return Reserve(which, value, m_core_timing->GetGlobalTimeNs().count() + DefaultTimeout); + return Reserve(which, value, m_kernel.HardwareTimer().GetTick() + DefaultTimeout); } bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { @@ -117,7 +116,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) { } if (m_current_hints[index] + value <= m_limit_values[index] && - (timeout < 0 || m_core_timing->GetGlobalTimeNs().count() < timeout)) { + (timeout < 0 || m_kernel.HardwareTimer().GetTick() < timeout)) { m_waiter_count++; m_cond_var.Wait(std::addressof(m_lock), timeout, false); m_waiter_count--; @@ -154,7 +153,7 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) { KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) { auto* resource_limit = KResourceLimit::Create(system.Kernel()); - resource_limit->Initialize(std::addressof(system.CoreTiming())); + resource_limit->Initialize(); // Initialize default resource limit values. // TODO(bunnei): These values are the system defaults, the limits for service processes are diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index d73bd3ceb..918dd69b2 100755 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -31,7 +31,7 @@ public: explicit KResourceLimit(KernelCore& kernel); ~KResourceLimit() override; - void Initialize(const Core::Timing::CoreTiming* core_timing); + void Initialize(); void Finalize() override; s64 GetLimitValue(LimitableResource which) const; @@ -57,7 +57,6 @@ private: mutable KLightLock m_lock; s32 m_waiter_count{}; KLightConditionVariable m_cond_var; - const Core::Timing::CoreTiming* m_core_timing{}; }; KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size); diff --git a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h index 87a273d4b..ba5357b20 100755 --- a/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h +++ b/src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h @@ -28,7 +28,7 @@ public: ~KScopedSchedulerLockAndSleep() { // Register the sleep. if (m_timeout_tick > 0) { - m_timer->RegisterTask(m_thread, m_timeout_tick); + m_timer->RegisterAbsoluteTask(m_thread, m_timeout_tick); } // Unlock the scheduler. diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 42c13e7df..ee144293b 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -231,7 +231,7 @@ struct KernelCore::Impl { void InitializeSystemResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing) { system_resource_limit = KResourceLimit::Create(system.Kernel()); - system_resource_limit->Initialize(&core_timing); + system_resource_limit->Initialize(); KResourceLimit::Register(kernel, system_resource_limit); const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()}; diff --git a/src/core/hle/kernel/svc/svc_address_arbiter.cpp b/src/core/hle/kernel/svc/svc_address_arbiter.cpp index 04cc5ea64..90ee43521 100755 --- a/src/core/hle/kernel/svc/svc_address_arbiter.cpp +++ b/src/core/hle/kernel/svc/svc_address_arbiter.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/kernel.h" @@ -52,7 +53,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ if (timeout_ns > 0) { const s64 offset_tick(timeout_ns); if (offset_tick > 0) { - timeout = offset_tick + 2; + timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { timeout = std::numeric_limits::max(); } diff --git a/src/core/hle/kernel/svc/svc_condition_variable.cpp b/src/core/hle/kernel/svc/svc_condition_variable.cpp index ca120d67e..bb678e6c5 100755 --- a/src/core/hle/kernel/svc/svc_condition_variable.cpp +++ b/src/core/hle/kernel/svc/svc_condition_variable.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/core.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/kernel.h" @@ -25,7 +26,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u if (timeout_ns > 0) { const s64 offset_tick(timeout_ns); if (offset_tick > 0) { - timeout = offset_tick + 2; + timeout = system.Kernel().HardwareTimer().GetTick() + offset_tick + 2; if (timeout <= 0) { timeout = std::numeric_limits::max(); } diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp index 373ae7c8d..6b5e1cb8d 100755 --- a/src/core/hle/kernel/svc/svc_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_ipc.cpp @@ -5,6 +5,7 @@ #include "common/scratch_buffer.h" #include "core/core.h" #include "core/hle/kernel/k_client_session.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_server_session.h" #include "core/hle/kernel/svc.h" @@ -82,12 +83,29 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_ad R_TRY(session->SendReply()); } + // Convert the timeout from nanoseconds to ticks. + // NOTE: Nintendo does not use this conversion logic in WaitSynchronization... + s64 timeout; + if (timeout_ns > 0) { + const s64 offset_tick(timeout_ns); + if (offset_tick > 0) { + timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; + if (timeout <= 0) { + timeout = std::numeric_limits::max(); + } + } else { + timeout = std::numeric_limits::max(); + } + } else { + timeout = timeout_ns; + } + // Wait for a message. while (true) { // Wait for an object. s32 index; Result result = KSynchronizationObject::Wait(kernel, std::addressof(index), objs.data(), - num_handles, timeout_ns); + num_handles, timeout); if (result == ResultTimedOut) { R_RETURN(result); } diff --git a/src/core/hle/kernel/svc/svc_resource_limit.cpp b/src/core/hle/kernel/svc/svc_resource_limit.cpp index 732bc017e..c8e820b6a 100755 --- a/src/core/hle/kernel/svc/svc_resource_limit.cpp +++ b/src/core/hle/kernel/svc/svc_resource_limit.cpp @@ -21,7 +21,7 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) { SCOPE_EXIT({ resource_limit->Close(); }); // Initialize the resource limit. - resource_limit->Initialize(std::addressof(system.CoreTiming())); + resource_limit->Initialize(); // Register the limit. KResourceLimit::Register(kernel, resource_limit); diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp index 366e8ed4a..8ebc1bd1c 100755 --- a/src/core/hle/kernel/svc/svc_synchronization.cpp +++ b/src/core/hle/kernel/svc/svc_synchronization.cpp @@ -4,6 +4,7 @@ #include "common/scope_exit.h" #include "common/scratch_buffer.h" #include "core/core.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/svc.h" @@ -83,9 +84,20 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha } }); + // Convert the timeout from nanoseconds to ticks. + s64 timeout; + if (timeout_ns > 0) { + u64 ticks = kernel.HardwareTimer().GetTick(); + ticks += timeout_ns; + ticks += 2; + + timeout = ticks; + } else { + timeout = timeout_ns; + } + // Wait on the objects. - Result res = - KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout_ns); + Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(), num_handles, timeout); R_SUCCEED_IF(res == ResultSessionClosed); R_RETURN(res); diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 92bcea72b..933b82e30 100755 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -4,6 +4,7 @@ #include "common/scope_exit.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scoped_resource_reservation.h" #include "core/hle/kernel/k_thread.h" @@ -42,9 +43,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); // Reserve a new thread from the process resource limit (waiting up to 100ms). - KScopedResourceReservation thread_reservation( - std::addressof(process), LimitableResource::ThreadCountMax, 1, - system.CoreTiming().GetGlobalTimeNs().count() + 100000000); + KScopedResourceReservation thread_reservation(std::addressof(process), + LimitableResource::ThreadCountMax, 1, + kernel.HardwareTimer().GetTick() + 100000000); R_UNLESS(thread_reservation.Succeeded(), ResultLimitReached); // Create the thread. @@ -102,20 +103,31 @@ void ExitThread(Core::System& system) { } /// Sleep the current thread -void SleepThread(Core::System& system, s64 nanoseconds) { +void SleepThread(Core::System& system, s64 ns) { auto& kernel = system.Kernel(); - const auto yield_type = static_cast(nanoseconds); + const auto yield_type = static_cast(ns); - LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); + LOG_TRACE(Kernel_SVC, "called nanoseconds={}", ns); // When the input tick is positive, sleep. - if (nanoseconds > 0) { + if (ns > 0) { // Convert the timeout from nanoseconds to ticks. // NOTE: Nintendo does not use this conversion logic in WaitSynchronization... + s64 timeout; + + const s64 offset_tick(ns); + if (offset_tick > 0) { + timeout = kernel.HardwareTimer().GetTick() + offset_tick + 2; + if (timeout <= 0) { + timeout = std::numeric_limits::max(); + } + } else { + timeout = std::numeric_limits::max(); + } // Sleep. // NOTE: Nintendo does not check the result of this sleep. - static_cast(GetCurrentThread(kernel).Sleep(nanoseconds)); + static_cast(GetCurrentThread(kernel).Sleep(timeout)); } else if (yield_type == Svc::YieldType::WithoutCoreMigration) { KScheduler::YieldWithoutCoreMigration(kernel); } else if (yield_type == Svc::YieldType::WithCoreMigration) { @@ -124,7 +136,6 @@ void SleepThread(Core::System& system, s64 nanoseconds) { KScheduler::YieldToAnyThread(kernel); } else { // Nintendo does nothing at all if an otherwise invalid value is passed. - ASSERT_MSG(false, "Unimplemented sleep yield type '{:016X}'!", nanoseconds); } }