diff options
author | Liam <byteslice@airmail.cc> | 2022-12-18 22:50:02 +0100 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2022-12-19 02:21:24 +0100 |
commit | c770f25ccb4755f6a6861037fbfdfdac55191348 (patch) | |
tree | eccc5140afa7a979800e8c27c1f4a2847adb283f | |
parent | kernel: add KHardwareTimer (diff) | |
download | yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar.gz yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar.bz2 yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar.lz yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar.xz yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.tar.zst yuzu-c770f25ccb4755f6a6861037fbfdfdac55191348.zip |
-rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 1 | ||||
-rw-r--r-- | src/core/hle/kernel/k_hardware_timer.cpp | 7 | ||||
-rw-r--r-- | src/core/hle/kernel/k_hardware_timer.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread.h | 8 | ||||
-rw-r--r-- | src/core/hle/kernel/k_thread_queue.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 20 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/time_manager.cpp | 44 | ||||
-rw-r--r-- | src/core/hle/kernel/time_manager.h | 41 |
11 files changed, 33 insertions, 117 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index dcccd0435..0252c8c31 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -294,8 +294,6 @@ add_library(core STATIC hle/kernel/svc_common.h hle/kernel/svc_types.h hle/kernel/svc_wrap.h - hle/kernel/time_manager.cpp - hle/kernel/time_manager.h hle/result.h hle/service/acc/acc.cpp hle/service/acc/acc.h diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index f85b11557..a442a3b98 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -10,7 +10,6 @@ #include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/svc_results.h" -#include "core/hle/kernel/time_manager.h" #include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp index afa777f9a..6bba79ea0 100644 --- a/src/core/hle/kernel/k_hardware_timer.cpp +++ b/src/core/hle/kernel/k_hardware_timer.cpp @@ -5,15 +5,13 @@ #include "core/core_timing.h" #include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/time_manager.h" namespace Kernel { void KHardwareTimer::Initialize() { // Create the timing callback to register with CoreTiming. m_event_type = Core::Timing::CreateEvent( - "KHardwareTimer::Callback", - [this](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) { + "KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) { reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask(); return std::nullopt; }); @@ -21,6 +19,7 @@ void KHardwareTimer::Initialize() { void KHardwareTimer::Finalize() { this->DisableInterrupt(); + m_event_type.reset(); } void KHardwareTimer::DoTask() { @@ -64,7 +63,7 @@ void KHardwareTimer::DisableInterrupt() { m_wakeup_time = std::numeric_limits<s64>::max(); } -s64 KHardwareTimer::GetTick() { +s64 KHardwareTimer::GetTick() const { return m_kernel.System().CoreTiming().GetGlobalTimeNs().count(); } diff --git a/src/core/hle/kernel/k_hardware_timer.h b/src/core/hle/kernel/k_hardware_timer.h index 2c88876b3..00bef6ea1 100644 --- a/src/core/hle/kernel/k_hardware_timer.h +++ b/src/core/hle/kernel/k_hardware_timer.h @@ -19,10 +19,14 @@ public: void Initialize(); void Finalize(); - s64 GetCount() { + s64 GetCount() const { return GetTick(); } + void RegisterTask(KTimerTask* task, s64 time_from_now) { + this->RegisterAbsoluteTask(task, GetTick() + time_from_now); + } + void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) { KScopedDisableDispatch dd{m_kernel}; KScopedSpinLock lk{this->GetLock()}; @@ -38,7 +42,7 @@ private: void EnableInterrupt(s64 wakeup_time); void DisableInterrupt(); bool GetInterruptEnabled(); - s64 GetTick(); + s64 GetTick() const; void DoTask(); private: 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 76c095e69..76db65a4d 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 @@ -5,9 +5,9 @@ #include "common/common_types.h" #include "core/hle/kernel/global_scheduler_context.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/time_manager.h" namespace Kernel { @@ -22,7 +22,7 @@ public: ~KScopedSchedulerLockAndSleep() { // Register the sleep. if (timeout_tick > 0) { - kernel.TimeManager().ScheduleTimeEvent(thread, timeout_tick); + kernel.HardwareTimer().RegisterTask(thread, timeout_tick); } // Unlock the scheduler. diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 1320451c0..7cd94a340 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -662,7 +662,7 @@ private: union SyncObjectBuffer { std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{}; std::array<Handle, - Svc::ArgumentHandleCountMax * (sizeof(KSynchronizationObject*) / sizeof(Handle))> + Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))> handles; constexpr SyncObjectBuffer() {} }; @@ -683,8 +683,10 @@ private: }; template <typename T> - requires(std::same_as<T, KThread> || std::same_as<T, RedBlackKeyType>) - static constexpr int Compare(const T& lhs, const KThread& rhs) { + requires( + std::same_as<T, KThread> || + std::same_as<T, RedBlackKeyType>) static constexpr int Compare(const T& lhs, + const KThread& rhs) { const u64 l_key = lhs.GetConditionVariableKey(); const u64 r_key = rhs.GetConditionVariableKey(); diff --git a/src/core/hle/kernel/k_thread_queue.cpp b/src/core/hle/kernel/k_thread_queue.cpp index 9f4e081ba..5f1dc97eb 100644 --- a/src/core/hle/kernel/k_thread_queue.cpp +++ b/src/core/hle/kernel/k_thread_queue.cpp @@ -1,9 +1,9 @@ // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_thread_queue.h" #include "core/hle/kernel/kernel.h" -#include "core/hle/kernel/time_manager.h" namespace Kernel { @@ -22,7 +22,7 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) { waiting_thread->ClearWaitQueue(); // Cancel the thread task. - kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); + kernel.HardwareTimer().CancelTask(waiting_thread); } void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { @@ -37,7 +37,7 @@ void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool // Cancel the thread task. if (cancel_timer_task) { - kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); + kernel.HardwareTimer().CancelTask(waiting_thread); } } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0eb74a422..b75bac5df 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -26,6 +26,7 @@ #include "core/hle/kernel/k_client_port.h" #include "core/hle/kernel/k_dynamic_resource_manager.h" #include "core/hle/kernel/k_handle_table.h" +#include "core/hle/kernel/k_hardware_timer.h" #include "core/hle/kernel/k_memory_layout.h" #include "core/hle/kernel/k_memory_manager.h" #include "core/hle/kernel/k_page_buffer.h" @@ -39,7 +40,6 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/service_thread.h" -#include "core/hle/kernel/time_manager.h" #include "core/hle/result.h" #include "core/hle/service/sm/sm.h" #include "core/memory.h" @@ -55,7 +55,7 @@ struct KernelCore::Impl { static constexpr size_t ReservedDynamicPageCount = 64; explicit Impl(Core::System& system_, KernelCore& kernel_) - : time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"}, + : service_threads_manager{1, "ServiceThreadsManager"}, service_thread_barrier{2}, system{system_} {} void SetMulticore(bool is_multi) { @@ -63,6 +63,9 @@ struct KernelCore::Impl { } void Initialize(KernelCore& kernel) { + hardware_timer = std::make_unique<Kernel::KHardwareTimer>(kernel); + hardware_timer->Initialize(); + global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel); global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); @@ -193,6 +196,9 @@ struct KernelCore::Impl { // Ensure that the object list container is finalized and properly shutdown. global_object_list_container->Finalize(); global_object_list_container.reset(); + + hardware_timer->Finalize(); + hardware_timer.reset(); } void CloseServices() { @@ -832,7 +838,7 @@ struct KernelCore::Impl { std::vector<KProcess*> process_list; std::atomic<KProcess*> current_process{}; std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; - Kernel::TimeManager time_manager; + std::unique_ptr<Kernel::KHardwareTimer> hardware_timer; Init::KSlabResourceCounts slab_resource_counts{}; KResourceLimit* system_resource_limit{}; @@ -1019,12 +1025,8 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() { return impl->schedulers[core_id].get(); } -Kernel::TimeManager& KernelCore::TimeManager() { - return impl->time_manager; -} - -const Kernel::TimeManager& KernelCore::TimeManager() const { - return impl->time_manager; +Kernel::KHardwareTimer& KernelCore::HardwareTimer() { + return *impl->hardware_timer; } Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 2e22fe0f6..8d22f8d2c 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -39,6 +39,7 @@ class KDynamicPageManager; class KEvent; class KEventInfo; class KHandleTable; +class KHardwareTimer; class KLinkedListNode; class KMemoryLayout; class KMemoryManager; @@ -63,7 +64,6 @@ class KCodeMemory; class PhysicalCore; class ServiceThread; class Synchronization; -class TimeManager; using ServiceInterfaceFactory = std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; @@ -175,11 +175,8 @@ public: /// Gets the an instance of the current physical CPU core. const Kernel::PhysicalCore& CurrentPhysicalCore() const; - /// Gets the an instance of the TimeManager Interface. - Kernel::TimeManager& TimeManager(); - - /// Gets the an instance of the TimeManager Interface. - const Kernel::TimeManager& TimeManager() const; + /// Gets the an instance of the hardware timer. + Kernel::KHardwareTimer& HardwareTimer(); /// Stops execution of 'id' core, in order to reschedule a new thread. void PrepareReschedule(std::size_t id); diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp deleted file mode 100644 index 5ee72c432..000000000 --- a/src/core/hle/kernel/time_manager.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include "common/assert.h" -#include "core/core.h" -#include "core/core_timing.h" -#include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/k_thread.h" -#include "core/hle/kernel/time_manager.h" - -namespace Kernel { - -TimeManager::TimeManager(Core::System& system_) : system{system_} { - time_manager_event_type = Core::Timing::CreateEvent( - "Kernel::TimeManagerCallback", - [this](std::uintptr_t thread_handle, s64 time, - std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> { - KThread* thread = reinterpret_cast<KThread*>(thread_handle); - { - KScopedSchedulerLock sl(system.Kernel()); - thread->OnTimer(); - } - return std::nullopt; - }); -} - -void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) { - std::scoped_lock lock{mutex}; - if (nanoseconds > 0) { - ASSERT(thread); - ASSERT(thread->GetState() != ThreadState::Runnable); - system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, - time_manager_event_type, - reinterpret_cast<uintptr_t>(thread)); - } -} - -void TimeManager::UnscheduleTimeEvent(KThread* thread) { - std::scoped_lock lock{mutex}; - system.CoreTiming().UnscheduleEvent(time_manager_event_type, - reinterpret_cast<uintptr_t>(thread)); -} - -} // namespace Kernel diff --git a/src/core/hle/kernel/time_manager.h b/src/core/hle/kernel/time_manager.h deleted file mode 100644 index 94d16b3b4..000000000 --- a/src/core/hle/kernel/time_manager.h +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include <memory> -#include <mutex> - -namespace Core { -class System; -} // namespace Core - -namespace Core::Timing { -struct EventType; -} // namespace Core::Timing - -namespace Kernel { - -class KThread; - -/** - * The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp - * method when the event is triggered. - */ -class TimeManager { -public: - explicit TimeManager(Core::System& system); - - /// Schedule a time event on `timetask` thread that will expire in 'nanoseconds' - void ScheduleTimeEvent(KThread* time_task, s64 nanoseconds); - - /// Unschedule an existing time event - void UnscheduleTimeEvent(KThread* thread); - -private: - Core::System& system; - std::shared_ptr<Core::Timing::EventType> time_manager_event_type; - std::mutex mutex; -}; - -} // namespace Kernel |