From 0bd9a4456c49b1e5de8f659682a814bb4b5854d2 Mon Sep 17 00:00:00 2001
From: Liam <byteslice@airmail.cc>
Date: Mon, 14 Aug 2023 18:12:06 -0400
Subject: [PATCH] kernel: remove relative task registration

---
 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 +++++++++++++------
 11 files changed, 67 insertions(+), 33 deletions(-)

diff --git a/src/core/hle/kernel/k_hardware_timer.h b/src/core/hle/kernel/k_hardware_timer.h
index 00bef6ea15..27f43cd194 100644
--- 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 fcee26a290..d8a63aaf8c 100644
--- 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 15e69af56b..b733ec8f81 100644
--- 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 c485022f53..b62415da70 100644
--- 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 ebe7582c65..a1134b7e26 100644
--- 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 04cc5ea64e..90ee435219 100644
--- 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<s64>::max();
             }
diff --git a/src/core/hle/kernel/svc/svc_condition_variable.cpp b/src/core/hle/kernel/svc/svc_condition_variable.cpp
index ca120d67e4..bb678e6c56 100644
--- 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<s64>::max();
             }
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 373ae7c8d5..6b5e1cb8d7 100644
--- 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<s64>::max();
+            }
+        } else {
+            timeout = std::numeric_limits<s64>::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 732bc017e9..c8e820b6a8 100644
--- 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 366e8ed4a2..8ebc1bd1cc 100644
--- 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 92bcea72b3..933b82e304 100644
--- 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<Svc::YieldType>(nanoseconds);
+    const auto yield_type = static_cast<Svc::YieldType>(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<s64>::max();
+            }
+        } else {
+            timeout = std::numeric_limits<s64>::max();
+        }
 
         // Sleep.
         // NOTE: Nintendo does not check the result of this sleep.
-        static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
+        static_cast<void>(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);
     }
 }