kernel/timer: fix period argument clamp handling
Commit 3e729b2b1c52 ("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>
diff --git a/kernel/timer.c b/kernel/timer.c
index 325224d..9de9768 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -52,6 +52,9 @@
!K_TIMEOUT_EQ(timer->period, K_FOREVER)) {
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
/* Exploit the fact that uptime during a kernel
* timeout handler reflects the time of the scheduled
@@ -64,8 +67,7 @@
* beginning of a tick, so need to defeat the "round
* down" behavior on timeout addition).
*/
- next = K_TIMEOUT_ABS_TICKS(k_uptime_ticks() + 1
- + timer->period.ticks);
+ next = K_TIMEOUT_ABS_TICKS(k_uptime_ticks() + 1 + next.ticks);
#endif
z_add_timeout(&timer->timeout, z_timer_expiration_handler,
next);
@@ -139,8 +141,8 @@
* to round up to the next tick (by convention it waits for
* "at least as long as the specified timeout"), but the
* period interval is always guaranteed to be reset from
- * within the timer ISR, so no round up is desired. Subtract
- * one.
+ * within the timer ISR, so no round up is desired and 1 is
+ * subtracted in there.
*
* Note that the duration (!) value gets the same treatment
* for backwards compatibility. This is unfortunate
@@ -148,10 +150,6 @@
* argument the same way k_sleep() does), but historical. The
* 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) {
duration.ticks = MAX(duration.ticks - 1, 0);
}