summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Subv2014-12-04 14:45:47 -0500
committerGravatar Subv2015-01-08 21:22:14 -0500
commit07044651ef2644451dc4f78045856ad078cb69fe (patch)
tree50113ade759854c60c0e91864f27f2f680993e84 /src/core/hle/kernel
parentMerge pull request #425 from Subv/coretiming (diff)
downloadyuzu-07044651ef2644451dc4f78045856ad078cb69fe.tar.gz
yuzu-07044651ef2644451dc4f78045856ad078cb69fe.tar.xz
yuzu-07044651ef2644451dc4f78045856ad078cb69fe.zip
SVC: Implemented the Timer service calls.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp4
-rw-r--r--src/core/hle/kernel/kernel.h1
-rw-r--r--src/core/hle/kernel/thread.h1
-rw-r--r--src/core/hle/kernel/timer.cpp142
-rw-r--r--src/core/hle/kernel/timer.h47
5 files changed, 194 insertions, 1 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e59ed1b57..084fd03ae 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -9,6 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
12#include "core/hle/kernel/timer.h"
12 13
13namespace Kernel { 14namespace Kernel {
14 15
@@ -105,12 +106,13 @@ void HandleTable::Clear() {
105/// Initialize the kernel 106/// Initialize the kernel
106void Init() { 107void Init() {
107 Kernel::ThreadingInit(); 108 Kernel::ThreadingInit();
109 Kernel::TimersInit();
108} 110}
109 111
110/// Shutdown the kernel 112/// Shutdown the kernel
111void Shutdown() { 113void Shutdown() {
112 Kernel::ThreadingShutdown(); 114 Kernel::ThreadingShutdown();
113 115 Kernel::TimersShutdown();
114 g_handle_table.Clear(); // Free all kernel objects 116 g_handle_table.Clear(); // Free all kernel objects
115} 117}
116 118
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 7f86fd07d..3e381d776 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -39,6 +39,7 @@ enum class HandleType : u32 {
39 Process = 8, 39 Process = 8,
40 AddressArbiter = 9, 40 AddressArbiter = 9,
41 Semaphore = 10, 41 Semaphore = 10,
42 Timer = 11
42}; 43};
43 44
44enum { 45enum {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 0e1397cd9..81736a866 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -43,6 +43,7 @@ enum WaitType {
43 WAITTYPE_MUTEX, 43 WAITTYPE_MUTEX,
44 WAITTYPE_SYNCH, 44 WAITTYPE_SYNCH,
45 WAITTYPE_ARB, 45 WAITTYPE_ARB,
46 WAITTYPE_TIMER,
46}; 47};
47 48
48namespace Kernel { 49namespace Kernel {
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
new file mode 100644
index 000000000..7ac669e31
--- /dev/null
+++ b/src/core/hle/kernel/timer.cpp
@@ -0,0 +1,142 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <set>
6
7#include "common/common.h"
8
9#include "core/core_timing.h"
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/timer.h"
12#include "core/hle/kernel/thread.h"
13
14namespace Kernel {
15
16class Timer : public Object {
17public:
18 std::string GetTypeName() const override { return "Timer"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Timer;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 ResetType reset_type; ///< The ResetType of this timer
25
26 bool signaled; ///< Whether the timer has been signaled or not
27 std::set<Handle> waiting_threads; ///< Threads that are waiting for the timer
28 std::string name; ///< Name of timer (optional)
29
30 u64 initial_delay; ///< The delay until the timer fires for the first time
31 u64 interval_delay; ///< The delay until the timer fires after the first time
32
33 ResultVal<bool> WaitSynchronization() override {
34 bool wait = !signaled;
35 if (wait) {
36 waiting_threads.insert(GetCurrentThreadHandle());
37 Kernel::WaitCurrentThread(WAITTYPE_TIMER, GetHandle());
38 }
39 return MakeResult<bool>(wait);
40 }
41};
42
43/**
44 * Creates a timer.
45 * @param handle Reference to handle for the newly created timer
46 * @param reset_type ResetType describing how to create timer
47 * @param name Optional name of timer
48 * @return Newly created Timer object
49 */
50Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
51 Timer* timer = new Timer;
52
53 handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE);
54
55 timer->reset_type = reset_type;
56 timer->signaled = false;
57 timer->name = name;
58 timer->initial_delay = 0;
59 timer->interval_delay = 0;
60 return timer;
61}
62
63ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) {
64 CreateTimer(*handle, reset_type, name);
65 return RESULT_SUCCESS;
66}
67
68ResultCode ClearTimer(Handle handle) {
69 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
70
71 if (timer == nullptr)
72 return InvalidHandle(ErrorModule::Kernel);
73
74 timer->signaled = false;
75 return RESULT_SUCCESS;
76}
77
78/// The event type of the generic timer callback event
79static int TimerCallbackEventType = -1;
80
81/// The timer callback event, called when a timer is fired
82static void TimerCallback(u64 timer_handle, int cycles_late) {
83 Timer* timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
84
85 if (timer == nullptr) {
86 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
87 return;
88 }
89
90 LOG_TRACE(Kernel, "Timer %u fired", timer_handle);
91
92 timer->signaled = true;
93
94 // Resume all waiting threads
95 for (Handle thread : timer->waiting_threads)
96 ResumeThreadFromWait(thread);
97
98 timer->waiting_threads.clear();
99
100 if (timer->reset_type == RESETTYPE_ONESHOT)
101 timer->signaled = false;
102
103 if (timer->interval_delay != 0) {
104 // Reschedule the timer with the interval delay
105 u64 interval_microseconds = timer->interval_delay / 1000;
106 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
107 TimerCallbackEventType, timer_handle);
108 }
109}
110
111ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
112 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
113
114 if (timer == nullptr)
115 return InvalidHandle(ErrorModule::Kernel);
116
117 timer->initial_delay = initial;
118 timer->interval_delay = interval;
119
120 u64 initial_microseconds = initial / 1000;
121 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
122 return RESULT_SUCCESS;
123}
124
125ResultCode CancelTimer(Handle handle) {
126 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle);
127
128 if (timer == nullptr)
129 return InvalidHandle(ErrorModule::Kernel);
130
131 CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
132 return RESULT_SUCCESS;
133}
134
135void TimersInit() {
136 TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
137}
138
139void TimersShutdown() {
140}
141
142} // namespace
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
new file mode 100644
index 000000000..f8aa66b60
--- /dev/null
+++ b/src/core/hle/kernel/timer.h
@@ -0,0 +1,47 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h"
10#include "core/hle/svc.h"
11
12namespace Kernel {
13
14/**
15 * Cancels a timer
16 * @param handle Handle of the timer to cancel
17 */
18ResultCode CancelTimer(Handle handle);
19
20/**
21 * Starts a timer with the specified initial delay and interval
22 * @param handle Handle of the timer to start
23 * @param initial Delay until the timer is first fired
24 * @param interval Delay until the timer is fired after the first time
25 */
26ResultCode SetTimer(Handle handle, s64 initial, s64 interval);
27
28/**
29 * Clears a timer
30 * @param handle Handle of the timer to clear
31 */
32ResultCode ClearTimer(Handle handle);
33
34/**
35 * Creates a timer
36 * @param Handle to newly created Timer object
37 * @param reset_type ResetType describing how to create the timer
38 * @param name Optional name of timer
39 * @return ResultCode of the error
40 */
41ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown");
42
43/// Initializes the required variables for timers
44void TimersInit();
45/// Tears down the timer variables
46void TimersShutdown();
47} // namespace