From 1db9f18a08732e38258104d4e4dc1c56a6064f88 Mon Sep 17 00:00:00 2001 From: Andy Ross Date: Tue, 25 Jun 2019 10:09:45 -0700 Subject: [PATCH] kernel/timeout: Remove "clock_always_on", replace with "SLOPPY_IDLE" This is an oddball API. It's untested. In fact testing its proper behavior requires very elaborate automation (you need a device outside the Zephyr hardware to measure real world time, and a mechanism for getting the device into and out of idle without using the timer driver). And this makes for needless difficulty managing code coverage metrics. It was always just a hint anyway. Mark the old API deprecated and replace it with a kconfig tunable. The effect of that is just to change the timeout value passed to the timer driver, where we can manage code coverage metrics more easily (only one driver cares to actually support this feature anyway). Signed-off-by: Andy Ross --- drivers/timer/Kconfig | 9 +++++++++ include/kernel.h | 34 ++++++++++++++++++++++------------ kernel/timeout.c | 19 +++---------------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 150fed2b991..413e9007ca1 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -244,6 +244,15 @@ config TIMER_READS_ITS_FREQUENCY_AT_RUNTIME The drivers select this option automatically when needed. Do not modify this unless you have a very good reason for it. +config SYSTEM_CLOCK_SLOPPY_IDLE + bool "Timer allowed to skew uptime clock during idle" + help + When true, the timer driver is not required to maintain a + correct system uptime count when the system enters idle. + Some platforms may take advantage of this to reduce the + overhead from regular interrupts required to handle counter + wraparound conditions. + config SYSTEM_CLOCK_INIT_PRIORITY int "System clock driver initialization priority" default 0 diff --git a/include/kernel.h b/include/kernel.h index 8840afc6a0b..b42c45e77e0 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -1672,26 +1672,36 @@ __syscall s64_t k_uptime_get(void); /** * @brief Enable clock always on in tickless kernel * - * This routine enables keeping the clock running (that is, it always - * keeps an active timer interrupt scheduled) when there are no timer - * events programmed in tickless kernel scheduling. This is necessary - * if the clock is used to track passage of time (e.g. via - * k_uptime_get_32()), otherwise the internal hardware counter may - * roll over between interrupts. + * Deprecated. This does nothing (it was always just a hint). This + * functionality has been migrated to the SYSTEM_CLOCK_SLOPPY_IDLE + * kconfig. * * @retval prev_status Previous status of always on flag */ -int k_enable_sys_clock_always_on(void); +/* LCOV_EXCL_START */ +__deprecated static inline int k_enable_sys_clock_always_on(void) +{ + __ASSERT(IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE), + "Please use CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE instead"); + + return !IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE); +} +/* LCOV_EXCL_STOP */ /** * @brief Disable clock always on in tickless kernel * - * This routine disables keeping the clock running when - * there are no timer events programmed in tickless kernel - * scheduling. To save power, this routine should be called - * immediately when clock is not used to track time. + * Deprecated. This does nothing (it was always just a hint). This + * functionality has been migrated to the SYS_CLOCK_SLOPPY_IDLE + * kconfig. */ -void k_disable_sys_clock_always_on(void); +/* LCOV_EXCL_START */ +__deprecated static inline void k_disable_sys_clock_always_on(void) +{ + __ASSERT(!IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE), + "Please use CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE instead"); +} +/* LCOV_EXCL_STOP */ /** * @brief Get system uptime (32-bit version). diff --git a/kernel/timeout.c b/kernel/timeout.c index 9801fb9714e..52bb2ef9903 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -21,7 +21,8 @@ static sys_dlist_t timeout_list = SYS_DLIST_STATIC_INIT(&timeout_list); static struct k_spinlock timeout_lock; -static bool can_wait_forever; +#define MAX_WAIT (IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE) \ + ? K_FOREVER : INT_MAX) /* Cycles left to process in the currently-executing z_clock_announce() */ static int announce_remaining; @@ -67,9 +68,8 @@ static s32_t elapsed(void) static s32_t next_timeout(void) { - int maxw = can_wait_forever ? K_FOREVER : INT_MAX; struct _timeout *to = first(); - s32_t ret = to == NULL ? maxw : MAX(0, to->dticks - elapsed()); + s32_t ret = to == NULL ? MAX_WAIT : MAX(0, to->dticks - elapsed()); #ifdef CONFIG_TIMESLICING if (_current_cpu->slice_ticks && _current_cpu->slice_ticks < ret) { @@ -209,19 +209,6 @@ void z_clock_announce(s32_t ticks) k_spin_unlock(&timeout_lock, key); } -int k_enable_sys_clock_always_on(void) -{ - int ret = !can_wait_forever; - - can_wait_forever = 0; - return ret; -} - -void k_disable_sys_clock_always_on(void) -{ - can_wait_forever = 1; -} - s64_t z_tick_get(void) { u64_t t = 0U;