Merge pull request #2421 from Subv/timers
Timers: Immediately signal the timer if it was started with an initial value of 0
This commit is contained in:
commit
fb5301cf6e
@ -52,9 +52,14 @@ void Timer::Set(s64 initial, s64 interval) {
|
|||||||
initial_delay = initial;
|
initial_delay = initial;
|
||||||
interval_delay = interval;
|
interval_delay = interval;
|
||||||
|
|
||||||
|
if (initial == 0) {
|
||||||
|
// Immediately invoke the callback
|
||||||
|
Signal(0);
|
||||||
|
} else {
|
||||||
u64 initial_microseconds = initial / 1000;
|
u64 initial_microseconds = initial / 1000;
|
||||||
CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
|
CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
|
||||||
callback_handle);
|
callback_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::Cancel() {
|
void Timer::Cancel() {
|
||||||
@ -72,6 +77,20 @@ void Timer::WakeupAllWaitingThreads() {
|
|||||||
signaled = false;
|
signaled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Timer::Signal(int cycles_late) {
|
||||||
|
LOG_TRACE(Kernel, "Timer %08" PRIx64 " fired", timer_handle);
|
||||||
|
|
||||||
|
// Resume all waiting threads
|
||||||
|
WakeupAllWaitingThreads();
|
||||||
|
|
||||||
|
if (interval_delay != 0) {
|
||||||
|
// Reschedule the timer with the interval delay
|
||||||
|
u64 interval_microseconds = interval_delay / 1000;
|
||||||
|
CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
|
||||||
|
timer_callback_event_type, callback_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The timer callback event, called when a timer is fired
|
/// The timer callback event, called when a timer is fired
|
||||||
static void TimerCallback(u64 timer_handle, int cycles_late) {
|
static void TimerCallback(u64 timer_handle, int cycles_late) {
|
||||||
SharedPtr<Timer> timer =
|
SharedPtr<Timer> timer =
|
||||||
@ -82,19 +101,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE(Kernel, "Timer %08" PRIx64 " fired", timer_handle);
|
timer->Signal(cycles_late);
|
||||||
|
|
||||||
timer->signaled = true;
|
|
||||||
|
|
||||||
// Resume all waiting threads
|
|
||||||
timer->WakeupAllWaitingThreads();
|
|
||||||
|
|
||||||
if (timer->interval_delay != 0) {
|
|
||||||
// Reschedule the timer with the interval delay
|
|
||||||
u64 interval_microseconds = timer->interval_delay / 1000;
|
|
||||||
CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
|
|
||||||
timer_callback_event_type, timer_handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimersInit() {
|
void TimersInit() {
|
||||||
|
@ -54,6 +54,14 @@ public:
|
|||||||
void Cancel();
|
void Cancel();
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals the timer, waking up any waiting threads and rescheduling it
|
||||||
|
* for the next interval.
|
||||||
|
* This method should not be called from outside the timer callback handler,
|
||||||
|
* lest multiple callback events get scheduled.
|
||||||
|
*/
|
||||||
|
void Signal(int cycles_late);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Timer();
|
Timer();
|
||||||
~Timer() override;
|
~Timer() override;
|
||||||
|
@ -837,6 +837,11 @@ static ResultCode SetTimer(Kernel::Handle handle, s64 initial, s64 interval) {
|
|||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
|
LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
|
||||||
|
|
||||||
|
if (initial < 0 || interval < 0) {
|
||||||
|
return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
|
||||||
|
ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
|
||||||
|
}
|
||||||
|
|
||||||
SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
|
SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
|
||||||
if (timer == nullptr)
|
if (timer == nullptr)
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
Loading…
Reference in New Issue
Block a user