Skip to content
Permalink
Browse files

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 <andrew.j.ross@intel.com>
  • Loading branch information...
andyross authored and andrewboie committed Jun 25, 2019
1 parent c129ac4 commit 1db9f18a08732e38258104d4e4dc1c56a6064f88
Showing with 34 additions and 28 deletions.
  1. +9 −0 drivers/timer/Kconfig
  2. +22 −12 include/kernel.h
  3. +3 −16 kernel/timeout.c
@@ -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
@@ -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).
@@ -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;

0 comments on commit 1db9f18

Please sign in to comment.
You can’t perform that action at this time.