aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/hle/kernel/timer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/timer.cpp')
-rw-r--r--src/core/hle/kernel/timer.cpp124
1 files changed, 39 insertions, 85 deletions
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 3b0452d4..4352fc99 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <set>
-
#include "common/common.h"
#include "core/core_timing.h"
@@ -13,77 +11,62 @@
namespace Kernel {
-class Timer : public Object {
-public:
- std::string GetTypeName() const override { return "Timer"; }
- std::string GetName() const override { return name; }
-
- static const HandleType HANDLE_TYPE = HandleType::Timer;
- HandleType GetHandleType() const override { return HANDLE_TYPE; }
-
- ResetType reset_type; ///< The ResetType of this timer
-
- bool signaled; ///< Whether the timer has been signaled or not
- std::set<Handle> waiting_threads; ///< Threads that are waiting for the timer
- std::string name; ///< Name of timer (optional)
-
- u64 initial_delay; ///< The delay until the timer fires for the first time
- u64 interval_delay; ///< The delay until the timer fires after the first time
-
- ResultVal<bool> WaitSynchronization() override {
- bool wait = !signaled;
- if (wait) {
- waiting_threads.insert(GetCurrentThread()->GetHandle());
- Kernel::WaitCurrentThread(WAITTYPE_TIMER, this);
- }
- return MakeResult<bool>(wait);
- }
-};
+/// The event type of the generic timer callback event
+static int timer_callback_event_type = -1;
+// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
+// us to simply use a pool index or similar.
+static Kernel::HandleTable timer_callback_handle_table;
-/**
- * Creates a timer.
- * @param handle Reference to handle for the newly created timer
- * @param reset_type ResetType describing how to create timer
- * @param name Optional name of timer
- * @return Newly created Timer object
- */
-Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
- Timer* timer = new Timer;
+Timer::Timer() {}
+Timer::~Timer() {}
- handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE);
+SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
+ SharedPtr<Timer> timer(new Timer);
timer->reset_type = reset_type;
timer->signaled = false;
- timer->name = name;
+ timer->name = std::move(name);
timer->initial_delay = 0;
timer->interval_delay = 0;
+ timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
+
return timer;
}
-ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) {
- CreateTimer(*handle, reset_type, name);
- return RESULT_SUCCESS;
+bool Timer::ShouldWait() {
+ return !signaled;
+}
+
+void Timer::Acquire() {
+ _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
}
-ResultCode ClearTimer(Handle handle) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
+void Timer::Set(s64 initial, s64 interval) {
+ // Ensure we get rid of any previous scheduled event
+ Cancel();
- timer->signaled = false;
- return RESULT_SUCCESS;
+ initial_delay = initial;
+ interval_delay = interval;
+
+ u64 initial_microseconds = initial / 1000;
+ CoreTiming::ScheduleEvent(usToCycles(initial_microseconds),
+ timer_callback_event_type, callback_handle);
}
-/// The event type of the generic timer callback event
-static int TimerCallbackEventType = -1;
+void Timer::Cancel() {
+ CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
+}
+
+void Timer::Clear() {
+ signaled = false;
+}
/// The timer callback event, called when a timer is fired
static void TimerCallback(u64 timer_handle, int cycles_late) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
+ SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle);
if (timer == nullptr) {
- LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
+ LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
return;
}
@@ -92,12 +75,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
timer->signaled = true;
// Resume all waiting threads
- for (Handle thread_handle : timer->waiting_threads) {
- if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle))
- thread->ResumeFromWait();
- }
-
- timer->waiting_threads.clear();
+ timer->WakeupAllWaitingThreads();
if (timer->reset_type == RESETTYPE_ONESHOT)
timer->signaled = false;
@@ -106,36 +84,12 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
// Reschedule the timer with the interval delay
u64 interval_microseconds = timer->interval_delay / 1000;
CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
- TimerCallbackEventType, timer_handle);
+ timer_callback_event_type, timer_handle);
}
}
-ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
-
- timer->initial_delay = initial;
- timer->interval_delay = interval;
-
- u64 initial_microseconds = initial / 1000;
- CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
- return RESULT_SUCCESS;
-}
-
-ResultCode CancelTimer(Handle handle) {
- SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
-
- if (timer == nullptr)
- return InvalidHandle(ErrorModule::Kernel);
-
- CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
- return RESULT_SUCCESS;
-}
-
void TimersInit() {
- TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
+ timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
}
void TimersShutdown() {