summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Matías Locatti2022-12-19 18:37:34 -0300
committerGravatar GitHub2022-12-19 18:37:34 -0300
commite44d1fe73cc5fac4cfab0d3d8660dbb46d60cafc (patch)
treeabfcbf2c097e1bb0b1297f0af90b94c055bc242c /src
parentMerge pull request #9471 from german77/input (diff)
parentkernel: remove TimeManager (diff)
downloadyuzu-e44d1fe73cc5fac4cfab0d3d8660dbb46d60cafc.tar.gz
yuzu-e44d1fe73cc5fac4cfab0d3d8660dbb46d60cafc.tar.xz
yuzu-e44d1fe73cc5fac4cfab0d3d8660dbb46d60cafc.zip
Merge pull request #9474 from liamwhite/timer
kernel: add KHardwareTimer
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt6
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp1
-rw-r--r--src/core/hle/kernel/k_hardware_timer.cpp74
-rw-r--r--src/core/hle/kernel/k_hardware_timer.h54
-rw-r--r--src/core/hle/kernel/k_hardware_timer_base.h92
-rw-r--r--src/core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h4
-rw-r--r--src/core/hle/kernel/k_thread.h8
-rw-r--r--src/core/hle/kernel/k_thread_queue.cpp6
-rw-r--r--src/core/hle/kernel/k_timer_task.h40
-rw-r--r--src/core/hle/kernel/kernel.cpp20
-rw-r--r--src/core/hle/kernel/kernel.h9
-rw-r--r--src/core/hle/kernel/time_manager.cpp44
-rw-r--r--src/core/hle/kernel/time_manager.h41
13 files changed, 290 insertions, 109 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index c6b5ac196..0252c8c31 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -201,6 +201,9 @@ add_library(core STATIC
201 hle/kernel/k_event_info.h 201 hle/kernel/k_event_info.h
202 hle/kernel/k_handle_table.cpp 202 hle/kernel/k_handle_table.cpp
203 hle/kernel/k_handle_table.h 203 hle/kernel/k_handle_table.h
204 hle/kernel/k_hardware_timer_base.h
205 hle/kernel/k_hardware_timer.cpp
206 hle/kernel/k_hardware_timer.h
204 hle/kernel/k_interrupt_manager.cpp 207 hle/kernel/k_interrupt_manager.cpp
205 hle/kernel/k_interrupt_manager.h 208 hle/kernel/k_interrupt_manager.h
206 hle/kernel/k_light_condition_variable.cpp 209 hle/kernel/k_light_condition_variable.cpp
@@ -268,6 +271,7 @@ add_library(core STATIC
268 hle/kernel/k_thread_local_page.h 271 hle/kernel/k_thread_local_page.h
269 hle/kernel/k_thread_queue.cpp 272 hle/kernel/k_thread_queue.cpp
270 hle/kernel/k_thread_queue.h 273 hle/kernel/k_thread_queue.h
274 hle/kernel/k_timer_task.h
271 hle/kernel/k_trace.h 275 hle/kernel/k_trace.h
272 hle/kernel/k_transfer_memory.cpp 276 hle/kernel/k_transfer_memory.cpp
273 hle/kernel/k_transfer_memory.h 277 hle/kernel/k_transfer_memory.h
@@ -290,8 +294,6 @@ add_library(core STATIC
290 hle/kernel/svc_common.h 294 hle/kernel/svc_common.h
291 hle/kernel/svc_types.h 295 hle/kernel/svc_types.h
292 hle/kernel/svc_wrap.h 296 hle/kernel/svc_wrap.h
293 hle/kernel/time_manager.cpp
294 hle/kernel/time_manager.h
295 hle/result.h 297 hle/result.h
296 hle/service/acc/acc.cpp 298 hle/service/acc/acc.cpp
297 hle/service/acc/acc.h 299 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 @@
10#include "core/hle/kernel/k_thread_queue.h" 10#include "core/hle/kernel/k_thread_queue.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/svc_results.h" 12#include "core/hle/kernel/svc_results.h"
13#include "core/hle/kernel/time_manager.h"
14#include "core/memory.h" 13#include "core/memory.h"
15 14
16namespace Kernel { 15namespace Kernel {
diff --git a/src/core/hle/kernel/k_hardware_timer.cpp b/src/core/hle/kernel/k_hardware_timer.cpp
new file mode 100644
index 000000000..6bba79ea0
--- /dev/null
+++ b/src/core/hle/kernel/k_hardware_timer.cpp
@@ -0,0 +1,74 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "core/core.h"
5#include "core/core_timing.h"
6#include "core/hle/kernel/k_hardware_timer.h"
7#include "core/hle/kernel/k_scheduler.h"
8
9namespace Kernel {
10
11void KHardwareTimer::Initialize() {
12 // Create the timing callback to register with CoreTiming.
13 m_event_type = Core::Timing::CreateEvent(
14 "KHardwareTimer::Callback", [](std::uintptr_t timer_handle, s64, std::chrono::nanoseconds) {
15 reinterpret_cast<KHardwareTimer*>(timer_handle)->DoTask();
16 return std::nullopt;
17 });
18}
19
20void KHardwareTimer::Finalize() {
21 this->DisableInterrupt();
22 m_event_type.reset();
23}
24
25void KHardwareTimer::DoTask() {
26 // Handle the interrupt.
27 {
28 KScopedSchedulerLock slk{m_kernel};
29 KScopedSpinLock lk(this->GetLock());
30
31 //! Ignore this event if needed.
32 if (!this->GetInterruptEnabled()) {
33 return;
34 }
35
36 // Disable the timer interrupt while we handle this.
37 this->DisableInterrupt();
38
39 if (const s64 next_time = this->DoInterruptTaskImpl(GetTick());
40 0 < next_time && next_time <= m_wakeup_time) {
41 // We have a next time, so we should set the time to interrupt and turn the interrupt
42 // on.
43 this->EnableInterrupt(next_time);
44 }
45 }
46
47 // Clear the timer interrupt.
48 // Kernel::GetInterruptManager().ClearInterrupt(KInterruptName_NonSecurePhysicalTimer,
49 // GetCurrentCoreId());
50}
51
52void KHardwareTimer::EnableInterrupt(s64 wakeup_time) {
53 this->DisableInterrupt();
54
55 m_wakeup_time = wakeup_time;
56 m_kernel.System().CoreTiming().ScheduleEvent(std::chrono::nanoseconds{m_wakeup_time},
57 m_event_type, reinterpret_cast<uintptr_t>(this),
58 true);
59}
60
61void KHardwareTimer::DisableInterrupt() {
62 m_kernel.System().CoreTiming().UnscheduleEvent(m_event_type, reinterpret_cast<uintptr_t>(this));
63 m_wakeup_time = std::numeric_limits<s64>::max();
64}
65
66s64 KHardwareTimer::GetTick() const {
67 return m_kernel.System().CoreTiming().GetGlobalTimeNs().count();
68}
69
70bool KHardwareTimer::GetInterruptEnabled() {
71 return m_wakeup_time != std::numeric_limits<s64>::max();
72}
73
74} // namespace Kernel
diff --git a/src/core/hle/kernel/k_hardware_timer.h b/src/core/hle/kernel/k_hardware_timer.h
new file mode 100644
index 000000000..00bef6ea1
--- /dev/null
+++ b/src/core/hle/kernel/k_hardware_timer.h
@@ -0,0 +1,54 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/kernel/k_hardware_timer_base.h"
7
8namespace Core::Timing {
9struct EventType;
10} // namespace Core::Timing
11
12namespace Kernel {
13
14class KHardwareTimer : /* public KInterruptTask, */ public KHardwareTimerBase {
15public:
16 explicit KHardwareTimer(KernelCore& kernel) : KHardwareTimerBase{kernel} {}
17
18 // Public API.
19 void Initialize();
20 void Finalize();
21
22 s64 GetCount() const {
23 return GetTick();
24 }
25
26 void RegisterTask(KTimerTask* task, s64 time_from_now) {
27 this->RegisterAbsoluteTask(task, GetTick() + time_from_now);
28 }
29
30 void RegisterAbsoluteTask(KTimerTask* task, s64 task_time) {
31 KScopedDisableDispatch dd{m_kernel};
32 KScopedSpinLock lk{this->GetLock()};
33
34 if (this->RegisterAbsoluteTaskImpl(task, task_time)) {
35 if (task_time <= m_wakeup_time) {
36 this->EnableInterrupt(task_time);
37 }
38 }
39 }
40
41private:
42 void EnableInterrupt(s64 wakeup_time);
43 void DisableInterrupt();
44 bool GetInterruptEnabled();
45 s64 GetTick() const;
46 void DoTask();
47
48private:
49 // Absolute time in nanoseconds
50 s64 m_wakeup_time{std::numeric_limits<s64>::max()};
51 std::shared_ptr<Core::Timing::EventType> m_event_type{};
52};
53
54} // namespace Kernel
diff --git a/src/core/hle/kernel/k_hardware_timer_base.h b/src/core/hle/kernel/k_hardware_timer_base.h
new file mode 100644
index 000000000..6318b35bd
--- /dev/null
+++ b/src/core/hle/kernel/k_hardware_timer_base.h
@@ -0,0 +1,92 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "core/hle/kernel/k_spin_lock.h"
7#include "core/hle/kernel/k_thread.h"
8#include "core/hle/kernel/k_timer_task.h"
9
10namespace Kernel {
11
12class KHardwareTimerBase {
13public:
14 explicit KHardwareTimerBase(KernelCore& kernel) : m_kernel{kernel} {}
15
16 void CancelTask(KTimerTask* task) {
17 KScopedDisableDispatch dd{m_kernel};
18 KScopedSpinLock lk{m_lock};
19
20 if (const s64 task_time = task->GetTime(); task_time > 0) {
21 this->RemoveTaskFromTree(task);
22 }
23 }
24
25protected:
26 KSpinLock& GetLock() {
27 return m_lock;
28 }
29
30 s64 DoInterruptTaskImpl(s64 cur_time) {
31 // We want to handle all tasks, returning the next time that a task is scheduled.
32 while (true) {
33 // Get the next task. If there isn't one, return 0.
34 KTimerTask* task = m_next_task;
35 if (task == nullptr) {
36 return 0;
37 }
38
39 // If the task needs to be done in the future, do it in the future and not now.
40 if (const s64 task_time = task->GetTime(); task_time > cur_time) {
41 return task_time;
42 }
43
44 // Remove the task from the tree of tasks, and update our next task.
45 this->RemoveTaskFromTree(task);
46
47 // Handle the task.
48 task->OnTimer();
49 }
50 }
51
52 bool RegisterAbsoluteTaskImpl(KTimerTask* task, s64 task_time) {
53 ASSERT(task_time > 0);
54
55 // Set the task's time, and insert it into our tree.
56 task->SetTime(task_time);
57 m_task_tree.insert(*task);
58
59 // Update our next task if relevant.
60 if (m_next_task != nullptr && m_next_task->GetTime() <= task_time) {
61 return false;
62 }
63 m_next_task = task;
64 return true;
65 }
66
67private:
68 void RemoveTaskFromTree(KTimerTask* task) {
69 // Erase from the tree.
70 auto it = m_task_tree.erase(m_task_tree.iterator_to(*task));
71
72 // Clear the task's scheduled time.
73 task->SetTime(0);
74
75 // Update our next task if relevant.
76 if (m_next_task == task) {
77 m_next_task = (it != m_task_tree.end()) ? std::addressof(*it) : nullptr;
78 }
79 }
80
81protected:
82 KernelCore& m_kernel;
83
84private:
85 using TimerTaskTree = Common::IntrusiveRedBlackTreeBaseTraits<KTimerTask>::TreeType<KTimerTask>;
86
87 KSpinLock m_lock{};
88 TimerTaskTree m_task_tree{};
89 KTimerTask* m_next_task{};
90};
91
92} // namespace Kernel
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 @@
5 5
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "core/hle/kernel/global_scheduler_context.h" 7#include "core/hle/kernel/global_scheduler_context.h"
8#include "core/hle/kernel/k_hardware_timer.h"
8#include "core/hle/kernel/k_thread.h" 9#include "core/hle/kernel/k_thread.h"
9#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
10#include "core/hle/kernel/time_manager.h"
11 11
12namespace Kernel { 12namespace Kernel {
13 13
@@ -22,7 +22,7 @@ public:
22 ~KScopedSchedulerLockAndSleep() { 22 ~KScopedSchedulerLockAndSleep() {
23 // Register the sleep. 23 // Register the sleep.
24 if (timeout_tick > 0) { 24 if (timeout_tick > 0) {
25 kernel.TimeManager().ScheduleTimeEvent(thread, timeout_tick); 25 kernel.HardwareTimer().RegisterTask(thread, timeout_tick);
26 } 26 }
27 27
28 // Unlock the scheduler. 28 // Unlock the scheduler.
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index dc52b4ed3..7cd94a340 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -22,6 +22,7 @@
22#include "core/hle/kernel/k_light_lock.h" 22#include "core/hle/kernel/k_light_lock.h"
23#include "core/hle/kernel/k_spin_lock.h" 23#include "core/hle/kernel/k_spin_lock.h"
24#include "core/hle/kernel/k_synchronization_object.h" 24#include "core/hle/kernel/k_synchronization_object.h"
25#include "core/hle/kernel/k_timer_task.h"
25#include "core/hle/kernel/k_worker_task.h" 26#include "core/hle/kernel/k_worker_task.h"
26#include "core/hle/kernel/slab_helpers.h" 27#include "core/hle/kernel/slab_helpers.h"
27#include "core/hle/kernel/svc_common.h" 28#include "core/hle/kernel/svc_common.h"
@@ -112,7 +113,8 @@ void SetCurrentThread(KernelCore& kernel, KThread* thread);
112[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel); 113[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
113 114
114class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>, 115class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,
115 public boost::intrusive::list_base_hook<> { 116 public boost::intrusive::list_base_hook<>,
117 public KTimerTask {
116 KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject); 118 KERNEL_AUTOOBJECT_TRAITS(KThread, KSynchronizationObject);
117 119
118private: 120private:
@@ -840,4 +842,8 @@ private:
840 KernelCore& kernel; 842 KernelCore& kernel;
841}; 843};
842 844
845inline void KTimerTask::OnTimer() {
846 static_cast<KThread*>(this)->OnTimer();
847}
848
843} // namespace Kernel 849} // namespace Kernel
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 @@
1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/kernel/k_hardware_timer.h"
4#include "core/hle/kernel/k_thread_queue.h" 5#include "core/hle/kernel/k_thread_queue.h"
5#include "core/hle/kernel/kernel.h" 6#include "core/hle/kernel/kernel.h"
6#include "core/hle/kernel/time_manager.h"
7 7
8namespace Kernel { 8namespace Kernel {
9 9
@@ -22,7 +22,7 @@ void KThreadQueue::EndWait(KThread* waiting_thread, Result wait_result) {
22 waiting_thread->ClearWaitQueue(); 22 waiting_thread->ClearWaitQueue();
23 23
24 // Cancel the thread task. 24 // Cancel the thread task.
25 kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); 25 kernel.HardwareTimer().CancelTask(waiting_thread);
26} 26}
27 27
28void KThreadQueue::CancelWait(KThread* waiting_thread, Result wait_result, bool cancel_timer_task) { 28void 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
37 37
38 // Cancel the thread task. 38 // Cancel the thread task.
39 if (cancel_timer_task) { 39 if (cancel_timer_task) {
40 kernel.TimeManager().UnscheduleTimeEvent(waiting_thread); 40 kernel.HardwareTimer().CancelTask(waiting_thread);
41 } 41 }
42} 42}
43 43
diff --git a/src/core/hle/kernel/k_timer_task.h b/src/core/hle/kernel/k_timer_task.h
new file mode 100644
index 000000000..66f0a5a90
--- /dev/null
+++ b/src/core/hle/kernel/k_timer_task.h
@@ -0,0 +1,40 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include "common/intrusive_red_black_tree.h"
7
8namespace Kernel {
9
10class KTimerTask : public Common::IntrusiveRedBlackTreeBaseNode<KTimerTask> {
11public:
12 static constexpr int Compare(const KTimerTask& lhs, const KTimerTask& rhs) {
13 if (lhs.GetTime() < rhs.GetTime()) {
14 return -1;
15 } else {
16 return 1;
17 }
18 }
19
20 constexpr explicit KTimerTask() = default;
21
22 constexpr void SetTime(s64 t) {
23 m_time = t;
24 }
25
26 constexpr s64 GetTime() const {
27 return m_time;
28 }
29
30 // NOTE: This is virtual in Nintendo's kernel. Prior to 13.0.0, KWaitObject was also a
31 // TimerTask; this is no longer the case. Since this is now KThread exclusive, we have
32 // devirtualized (see inline declaration for this inside k_thread.h).
33 void OnTimer();
34
35private:
36 // Absolute time in nanoseconds
37 s64 m_time{};
38};
39
40} // namespace Kernel
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 @@
26#include "core/hle/kernel/k_client_port.h" 26#include "core/hle/kernel/k_client_port.h"
27#include "core/hle/kernel/k_dynamic_resource_manager.h" 27#include "core/hle/kernel/k_dynamic_resource_manager.h"
28#include "core/hle/kernel/k_handle_table.h" 28#include "core/hle/kernel/k_handle_table.h"
29#include "core/hle/kernel/k_hardware_timer.h"
29#include "core/hle/kernel/k_memory_layout.h" 30#include "core/hle/kernel/k_memory_layout.h"
30#include "core/hle/kernel/k_memory_manager.h" 31#include "core/hle/kernel/k_memory_manager.h"
31#include "core/hle/kernel/k_page_buffer.h" 32#include "core/hle/kernel/k_page_buffer.h"
@@ -39,7 +40,6 @@
39#include "core/hle/kernel/kernel.h" 40#include "core/hle/kernel/kernel.h"
40#include "core/hle/kernel/physical_core.h" 41#include "core/hle/kernel/physical_core.h"
41#include "core/hle/kernel/service_thread.h" 42#include "core/hle/kernel/service_thread.h"
42#include "core/hle/kernel/time_manager.h"
43#include "core/hle/result.h" 43#include "core/hle/result.h"
44#include "core/hle/service/sm/sm.h" 44#include "core/hle/service/sm/sm.h"
45#include "core/memory.h" 45#include "core/memory.h"
@@ -55,7 +55,7 @@ struct KernelCore::Impl {
55 static constexpr size_t ReservedDynamicPageCount = 64; 55 static constexpr size_t ReservedDynamicPageCount = 64;
56 56
57 explicit Impl(Core::System& system_, KernelCore& kernel_) 57 explicit Impl(Core::System& system_, KernelCore& kernel_)
58 : time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"}, 58 : service_threads_manager{1, "ServiceThreadsManager"},
59 service_thread_barrier{2}, system{system_} {} 59 service_thread_barrier{2}, system{system_} {}
60 60
61 void SetMulticore(bool is_multi) { 61 void SetMulticore(bool is_multi) {
@@ -63,6 +63,9 @@ struct KernelCore::Impl {
63 } 63 }
64 64
65 void Initialize(KernelCore& kernel) { 65 void Initialize(KernelCore& kernel) {
66 hardware_timer = std::make_unique<Kernel::KHardwareTimer>(kernel);
67 hardware_timer->Initialize();
68
66 global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel); 69 global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel);
67 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); 70 global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
68 global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); 71 global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
@@ -193,6 +196,9 @@ struct KernelCore::Impl {
193 // Ensure that the object list container is finalized and properly shutdown. 196 // Ensure that the object list container is finalized and properly shutdown.
194 global_object_list_container->Finalize(); 197 global_object_list_container->Finalize();
195 global_object_list_container.reset(); 198 global_object_list_container.reset();
199
200 hardware_timer->Finalize();
201 hardware_timer.reset();
196 } 202 }
197 203
198 void CloseServices() { 204 void CloseServices() {
@@ -832,7 +838,7 @@ struct KernelCore::Impl {
832 std::vector<KProcess*> process_list; 838 std::vector<KProcess*> process_list;
833 std::atomic<KProcess*> current_process{}; 839 std::atomic<KProcess*> current_process{};
834 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context; 840 std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
835 Kernel::TimeManager time_manager; 841 std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
836 842
837 Init::KSlabResourceCounts slab_resource_counts{}; 843 Init::KSlabResourceCounts slab_resource_counts{};
838 KResourceLimit* system_resource_limit{}; 844 KResourceLimit* system_resource_limit{};
@@ -1019,12 +1025,8 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
1019 return impl->schedulers[core_id].get(); 1025 return impl->schedulers[core_id].get();
1020} 1026}
1021 1027
1022Kernel::TimeManager& KernelCore::TimeManager() { 1028Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
1023 return impl->time_manager; 1029 return *impl->hardware_timer;
1024}
1025
1026const Kernel::TimeManager& KernelCore::TimeManager() const {
1027 return impl->time_manager;
1028} 1030}
1029 1031
1030Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { 1032Core::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;
39class KEvent; 39class KEvent;
40class KEventInfo; 40class KEventInfo;
41class KHandleTable; 41class KHandleTable;
42class KHardwareTimer;
42class KLinkedListNode; 43class KLinkedListNode;
43class KMemoryLayout; 44class KMemoryLayout;
44class KMemoryManager; 45class KMemoryManager;
@@ -63,7 +64,6 @@ class KCodeMemory;
63class PhysicalCore; 64class PhysicalCore;
64class ServiceThread; 65class ServiceThread;
65class Synchronization; 66class Synchronization;
66class TimeManager;
67 67
68using ServiceInterfaceFactory = 68using ServiceInterfaceFactory =
69 std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>; 69 std::function<KClientPort&(Service::SM::ServiceManager&, Core::System&)>;
@@ -175,11 +175,8 @@ public:
175 /// Gets the an instance of the current physical CPU core. 175 /// Gets the an instance of the current physical CPU core.
176 const Kernel::PhysicalCore& CurrentPhysicalCore() const; 176 const Kernel::PhysicalCore& CurrentPhysicalCore() const;
177 177
178 /// Gets the an instance of the TimeManager Interface. 178 /// Gets the an instance of the hardware timer.
179 Kernel::TimeManager& TimeManager(); 179 Kernel::KHardwareTimer& HardwareTimer();
180
181 /// Gets the an instance of the TimeManager Interface.
182 const Kernel::TimeManager& TimeManager() const;
183 180
184 /// Stops execution of 'id' core, in order to reschedule a new thread. 181 /// Stops execution of 'id' core, in order to reschedule a new thread.
185 void PrepareReschedule(std::size_t id); 182 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 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/assert.h"
5#include "core/core.h"
6#include "core/core_timing.h"
7#include "core/hle/kernel/k_scheduler.h"
8#include "core/hle/kernel/k_thread.h"
9#include "core/hle/kernel/time_manager.h"
10
11namespace Kernel {
12
13TimeManager::TimeManager(Core::System& system_) : system{system_} {
14 time_manager_event_type = Core::Timing::CreateEvent(
15 "Kernel::TimeManagerCallback",
16 [this](std::uintptr_t thread_handle, s64 time,
17 std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
18 KThread* thread = reinterpret_cast<KThread*>(thread_handle);
19 {
20 KScopedSchedulerLock sl(system.Kernel());
21 thread->OnTimer();
22 }
23 return std::nullopt;
24 });
25}
26
27void TimeManager::ScheduleTimeEvent(KThread* thread, s64 nanoseconds) {
28 std::scoped_lock lock{mutex};
29 if (nanoseconds > 0) {
30 ASSERT(thread);
31 ASSERT(thread->GetState() != ThreadState::Runnable);
32 system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds},
33 time_manager_event_type,
34 reinterpret_cast<uintptr_t>(thread));
35 }
36}
37
38void TimeManager::UnscheduleTimeEvent(KThread* thread) {
39 std::scoped_lock lock{mutex};
40 system.CoreTiming().UnscheduleEvent(time_manager_event_type,
41 reinterpret_cast<uintptr_t>(thread));
42}
43
44} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <memory>
7#include <mutex>
8
9namespace Core {
10class System;
11} // namespace Core
12
13namespace Core::Timing {
14struct EventType;
15} // namespace Core::Timing
16
17namespace Kernel {
18
19class KThread;
20
21/**
22 * The `TimeManager` takes care of scheduling time events on threads and executes their TimeUp
23 * method when the event is triggered.
24 */
25class TimeManager {
26public:
27 explicit TimeManager(Core::System& system);
28
29 /// Schedule a time event on `timetask` thread that will expire in 'nanoseconds'
30 void ScheduleTimeEvent(KThread* time_task, s64 nanoseconds);
31
32 /// Unschedule an existing time event
33 void UnscheduleTimeEvent(KThread* thread);
34
35private:
36 Core::System& system;
37 std::shared_ptr<Core::Timing::EventType> time_manager_event_type;
38 std::mutex mutex;
39};
40
41} // namespace Kernel