mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	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
					
				
					 3 changed files with 36 additions and 16 deletions
				
			
		|  | @ -52,9 +52,14 @@ void Timer::Set(s64 initial, s64 interval) { | ||||||
|     initial_delay = initial; |     initial_delay = initial; | ||||||
|     interval_delay = interval; |     interval_delay = interval; | ||||||
| 
 | 
 | ||||||
|     u64 initial_microseconds = initial / 1000; |     if (initial == 0) { | ||||||
|     CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, |         // Immediately invoke the callback
 | ||||||
|                               callback_handle); |         Signal(0); | ||||||
|  |     } else { | ||||||
|  |         u64 initial_microseconds = initial / 1000; | ||||||
|  |         CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, | ||||||
|  |                                   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…
	
	Add table
		Add a link
		
	
		Reference in a new issue