timer: Clean up hairy tickless APIs

The tickless driver had a bunch of "hairy" APIs which forced the timer
drivers to do needless low-level accounting for the benefit of the
kernel, all of which then proceeded to implement them via cut and
paste.  Specifically the "program_time" calls forced the driver to
expose to the kernel exactly when the next interrupt was due and how
much time had elapsed, in a parallel API to the existing "what time is
it" and "announce a tick" interrupts that carry the same information.

Remove these from the kernel, replacing them with synthesized logic
written in terms of the simpler APIs.

In some cases there will be a performance impact due to the use of the
64 bit uptime call, but that will go away soon.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2018-09-21 11:54:57 -07:00 committed by Anas Nashif
commit 722a888ef7
6 changed files with 34 additions and 40 deletions

View file

@ -8,16 +8,18 @@
* included only once in a single compilation.
*/
#ifdef CONFIG_TICKLESS_KERNEL
void _set_time(u32_t time);
#endif
#ifdef CONFIG_TICKLESS_IDLE
void _timer_idle_enter(s32_t ticks);
void z_clock_idle_exit(void);
#endif
#ifdef CONFIG_TICKLESS_KERNEL
void _set_time(u32_t time);
extern u32_t _get_program_time(void);
extern u32_t _get_remaining_program_time(void);
extern u32_t _get_elapsed_program_time(void);
#endif
extern void z_clock_set_timeout(s32_t ticks, bool idle)
{
#ifdef CONFIG_TICKLESS_KERNEL

View file

@ -109,12 +109,6 @@ extern void z_clock_announce(s32_t ticks);
*/
extern u64_t z_clock_uptime(void);
#ifdef CONFIG_TICKLESS_KERNEL
extern u32_t _get_program_time(void);
extern u32_t _get_remaining_program_time(void);
extern u32_t _get_elapsed_program_time(void);
#endif
#ifdef __cplusplus
}
#endif

View file

@ -13,6 +13,8 @@
#include <power.h>
#include <stdbool.h>
extern u64_t z_last_tick_announced;
#if defined(CONFIG_TICKLESS_IDLE)
/*
* Idle time must be this value or higher for timer to go into tickless idle
@ -72,7 +74,7 @@ static void sys_power_save_idle(s32_t ticks)
{
#ifdef CONFIG_TICKLESS_KERNEL
if (ticks != K_FOREVER) {
ticks -= _get_elapsed_program_time();
ticks -= (int)(z_clock_uptime() - z_last_tick_announced);
if (!ticks) {
/*
* Timer has expired or about to expire

View file

@ -21,6 +21,8 @@
extern "C" {
#endif
extern u64_t z_last_tick_announced;
/* initialize the timeouts part of k_thread when enabled in the kernel */
static inline void _init_timeout(struct _timeout *t, _timeout_func_t func)
@ -172,6 +174,16 @@ static inline void _dump_timeout_q(void)
#endif
}
/* find the closest deadline in the timeout queue */
static inline s32_t _get_next_timeout_expiry(void)
{
struct _timeout *t = (struct _timeout *)
sys_dlist_peek_head(&_timeout_q);
return t ? t->delta_ticks_from_prev : K_FOREVER;
}
/*
* Add timeout to timeout queue. Record waiting thread and wait queue if any.
*
@ -229,11 +241,9 @@ static inline void _add_timeout(struct k_thread *thread,
* This is like adding this timout back in history.
*/
u32_t adjusted_timeout;
u32_t program_time = _get_program_time();
if (program_time > 0) {
*delta += _get_elapsed_program_time();
}
*delta += (int)(z_clock_uptime() - z_last_tick_announced);
adjusted_timeout = *delta;
#endif
SYS_DLIST_FOR_EACH_CONTAINER(&_timeout_q, in_q, node) {
@ -255,7 +265,7 @@ inserted:
_dump_timeout_q();
#ifdef CONFIG_TICKLESS_KERNEL
if (!program_time || (adjusted_timeout < program_time)) {
if (adjusted_timeout < _get_next_timeout_expiry()) {
z_clock_set_timeout(adjusted_timeout, false);
}
#endif
@ -276,16 +286,6 @@ static inline void _add_thread_timeout(struct k_thread *thread,
_add_timeout(thread, &thread->base.timeout, wait_q, timeout_in_ticks);
}
/* find the closest deadline in the timeout queue */
static inline s32_t _get_next_timeout_expiry(void)
{
struct _timeout *t = (struct _timeout *)
sys_dlist_peek_head(&_timeout_q);
return t ? t->delta_ticks_from_prev : K_FOREVER;
}
#ifdef __cplusplus
}
#endif

View file

@ -648,17 +648,11 @@ void _update_time_slice_before_swap(void)
return;
}
u32_t remaining = _get_remaining_program_time();
if (!remaining || (_time_slice_duration < remaining)) {
z_clock_set_timeout(_time_slice_duration, false);
} else {
/* Account previous elapsed time and reprogram
* timer with remaining time
*/
z_clock_set_timeout(remaining, false);
}
int elapsed = (int)(z_clock_uptime() - z_last_tick_announced);
int next_timeout = _get_next_timeout_expiry() - elapsed;
int t = min(_time_slice_duration, next_timeout);
z_clock_set_timeout(t, false);
#endif
/* Restart time slice count at new thread switch */
_time_slice_elapsed = 0;

View file

@ -36,6 +36,8 @@ int z_clock_hw_cycles_per_sec;
*/
static volatile u64_t tick_count;
u64_t z_last_tick_announced;
#ifdef CONFIG_TICKLESS_KERNEL
/*
* If this flag is set, system clock will run continuously even if
@ -291,6 +293,8 @@ static void handle_time_slicing(s32_t ticks)
*/
void z_clock_announce(s32_t ticks)
{
z_last_tick_announced += ticks;
#ifdef CONFIG_SMP
/* sys_clock timekeeping happens only on the main CPU */
if (_arch_curr_cpu()->id) {
@ -319,9 +323,7 @@ void z_clock_announce(s32_t ticks)
next_to = !next_to || (next_ts
&& next_to) > next_ts ? next_ts : next_to;
u32_t remaining = _get_remaining_program_time();
if ((!remaining && next_to) || (next_to < remaining)) {
if (next_to) {
/* Clears current program if next_to = 0 and remaining > 0 */
int dt = next_to ? next_to : (_sys_clock_always_on ? INT_MAX : K_FOREVER);
z_clock_set_timeout(dt, false);