kernel/timeout: fix k_timer_remaining_get() when tickless

In some circumstances (e.g., a tickless kernel), k_timer_remaining_get()
would not account for time passed that didn't involve clock interrupts.
This adds a simple fix for that, and adds a test case.  In addition, the
return value of k_timer_remaining_get() is clamped at 0 in the case of
overdue timers and the API description is adjusted to reflect this.

Fixes: #13353

Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
Charles E. Youse 2019-03-01 10:51:04 -08:00 committed by Andrew Boie
commit 0ad4022e51
4 changed files with 34 additions and 4 deletions

View file

@ -1561,7 +1561,8 @@ __syscall u32_t k_timer_remaining_get(struct k_timer *timer);
static inline u32_t _impl_k_timer_remaining_get(struct k_timer *timer)
{
return (u32_t)__ticks_to_ms(z_timeout_remaining(&timer->timeout));
const s32_t ticks = z_timeout_remaining(&timer->timeout);
return (ticks > 0) ? (u32_t)__ticks_to_ms(ticks) : 0U;
}
/**

View file

@ -134,7 +134,7 @@ s32_t z_timeout_remaining(struct _timeout *timeout)
}
}
return ticks;
return ticks - elapsed();
}
s32_t _get_next_timeout_expiry(void)

View file

@ -484,6 +484,33 @@ void test_timer_user_data(void)
}
}
/**
* @brief Test accuracy of k_timer_remaining_get()
*
* Validate countdown of time to expiration
*
* Starts a timer, busy-waits for half the DURATION, then checks the
* remaining time to expiration and stops the timer. The remaining time
* should reflect the passage of at least the busy-wait interval.
*
* @ingroup kernel_timer_tests
*
* @see k_timer_init(), k_timer_start(), k_timer_stop(),
* k_timer_remaining_get()
*/
void test_timer_remaining_get(void)
{
u32_t remaining;
init_timer_data();
k_timer_init(&timer, NULL, NULL);
k_timer_start(&timer, DURATION, 0);
busy_wait_ms(DURATION / 2);
remaining = k_timer_remaining_get(&timer);
k_timer_stop(&timer);
zassert_true(remaining <= (DURATION / 2), NULL);
}
void test_main(void)
{
@ -496,6 +523,7 @@ void test_main(void)
ztest_unit_test(test_timer_status_get_anytime),
ztest_unit_test(test_timer_status_sync),
ztest_unit_test(test_timer_k_define),
ztest_unit_test(test_timer_user_data));
ztest_unit_test(test_timer_user_data),
ztest_unit_test(test_timer_remaining_get));
ztest_run_test_suite(timer_api);
}

View file

@ -1,8 +1,9 @@
common:
arch_exclude: x86_64
tests:
kernel.timer:
tags: kernel
kernel.timer.tickless:
build_only: true
extra_args: CONF_FILE="prj_tickless.conf"
arch_exclude: riscv32 nios2 posix
tags: kernel