POSIX timer: Optimize overrun check by replacing loop with division.

Converted the timer overrun check from a loop-based approach to a division-based method. This change ensures a deterministic worst-case execution time (WCET), even if it might not outperform the loop in average scenarios.

Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit is contained in:
ouyangxiangzhen
2024-09-13 17:57:25 +08:00
committed by Xiang Xiao
parent 578ecef975
commit 5a01f0f7f6
+17 -11
View File
@@ -98,6 +98,7 @@ static inline void timer_restart(FAR struct posix_timer_s *timer,
{ {
clock_t ticks; clock_t ticks;
sclock_t delay; sclock_t delay;
sclock_t frame;
/* If this is a repetitive timer, then restart the watchdog */ /* If this is a repetitive timer, then restart the watchdog */
@@ -106,19 +107,24 @@ static inline void timer_restart(FAR struct posix_timer_s *timer,
/* Check whether next expected time is reached */ /* Check whether next expected time is reached */
ticks = clock_systime_ticks(); ticks = clock_systime_ticks();
timer->pt_overrun = 0; delay = ticks - timer->pt_expected;
for (; ; ) /* Calculate the number of timer overruns and the next expected tick.
{ * The next expired tick frame can be computed as align up:
timer->pt_expected += timer->pt_delay; * frame <- (elapsed_ticks + pt_delay) / pt_delay
delay = timer->pt_expected - ticks; * For instance:
if (delay > 0) * | pt_delay | pt_delay | pt_delay | ... |
{ * ^ pt_expected ^ ticks ^ next pt_expected
break; * In this case, frame equals 3.
} * Then, pt_overrun <- frame - 1 and
* the next pt_expected <- pt_expected + frame * pt_delay.
* Assumption of correctness:
* (delay + timer->pt_delay) should not overflow.
*/
timer->pt_overrun++; frame = (delay + timer->pt_delay) / timer->pt_delay;
} timer->pt_overrun = frame - 1;
timer->pt_expected += frame * timer->pt_delay;
wd_start_abstick(&timer->pt_wdog, timer->pt_expected, wd_start_abstick(&timer->pt_wdog, timer->pt_expected,
timer_timeout, itimer); timer_timeout, itimer);