kernel/timer: fix period argument clamp handling
Commit 3e729b2b1c ("kernel/timer: Correctly clamp period argument")
increased the lower limit to 1 so that it wouldn't conflict with a
K_NO_WAIT. But in doing so it enforced a minimum period of 2 ticks.
And the subtraction must obviously be avoided if the period is zero, etc.
Instead of doing this masquerade in k_timer_start(), let's move the
subtraction and clamping in z_timer_expiration_handler() right before
registering a new timeout. It makes the code cleaner, and then it is
possible to have single-tick periods again.
Whith this, timer_jitter_drift in tests/kernel/timer/timer_behavior does
pass with any CONFIG_SYS_CLOCK_TICKS_PER_SEC value, even when the tick
period is equal or larger than the specified timer period for the test
which failed the test before.
Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
This commit is contained in:
parent
f21051b728
commit
6a51a10dec
1 changed files with 6 additions and 8 deletions
|
|
@ -52,6 +52,9 @@ void z_timer_expiration_handler(struct _timeout *t)
|
||||||
!K_TIMEOUT_EQ(timer->period, K_FOREVER)) {
|
!K_TIMEOUT_EQ(timer->period, K_FOREVER)) {
|
||||||
k_timeout_t next = timer->period;
|
k_timeout_t next = timer->period;
|
||||||
|
|
||||||
|
/* see note about z_add_timeout() in z_impl_k_timer_start() */
|
||||||
|
next.ticks = MAX(next.ticks - 1, 0);
|
||||||
|
|
||||||
#ifdef CONFIG_TIMEOUT_64BIT
|
#ifdef CONFIG_TIMEOUT_64BIT
|
||||||
/* Exploit the fact that uptime during a kernel
|
/* Exploit the fact that uptime during a kernel
|
||||||
* timeout handler reflects the time of the scheduled
|
* timeout handler reflects the time of the scheduled
|
||||||
|
|
@ -64,8 +67,7 @@ void z_timer_expiration_handler(struct _timeout *t)
|
||||||
* beginning of a tick, so need to defeat the "round
|
* beginning of a tick, so need to defeat the "round
|
||||||
* down" behavior on timeout addition).
|
* down" behavior on timeout addition).
|
||||||
*/
|
*/
|
||||||
next = K_TIMEOUT_ABS_TICKS(k_uptime_ticks() + 1
|
next = K_TIMEOUT_ABS_TICKS(k_uptime_ticks() + 1 + next.ticks);
|
||||||
+ timer->period.ticks);
|
|
||||||
#endif
|
#endif
|
||||||
z_add_timeout(&timer->timeout, z_timer_expiration_handler,
|
z_add_timeout(&timer->timeout, z_timer_expiration_handler,
|
||||||
next);
|
next);
|
||||||
|
|
@ -139,8 +141,8 @@ void z_impl_k_timer_start(struct k_timer *timer, k_timeout_t duration,
|
||||||
* to round up to the next tick (by convention it waits for
|
* to round up to the next tick (by convention it waits for
|
||||||
* "at least as long as the specified timeout"), but the
|
* "at least as long as the specified timeout"), but the
|
||||||
* period interval is always guaranteed to be reset from
|
* period interval is always guaranteed to be reset from
|
||||||
* within the timer ISR, so no round up is desired. Subtract
|
* within the timer ISR, so no round up is desired and 1 is
|
||||||
* one.
|
* subtracted in there.
|
||||||
*
|
*
|
||||||
* Note that the duration (!) value gets the same treatment
|
* Note that the duration (!) value gets the same treatment
|
||||||
* for backwards compatibility. This is unfortunate
|
* for backwards compatibility. This is unfortunate
|
||||||
|
|
@ -148,10 +150,6 @@ void z_impl_k_timer_start(struct k_timer *timer, k_timeout_t duration,
|
||||||
* argument the same way k_sleep() does), but historical. The
|
* argument the same way k_sleep() does), but historical. The
|
||||||
* timer_api test relies on this behavior.
|
* timer_api test relies on this behavior.
|
||||||
*/
|
*/
|
||||||
if (!K_TIMEOUT_EQ(period, K_FOREVER) && period.ticks != 0 &&
|
|
||||||
Z_TICK_ABS(period.ticks) < 0) {
|
|
||||||
period.ticks = MAX(period.ticks - 1, 1);
|
|
||||||
}
|
|
||||||
if (Z_TICK_ABS(duration.ticks) < 0) {
|
if (Z_TICK_ABS(duration.ticks) < 0) {
|
||||||
duration.ticks = MAX(duration.ticks - 1, 0);
|
duration.ticks = MAX(duration.ticks - 1, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue