Re: [RFC] Nanokernel timers rework proposal

Benjamin Walsh <benjamin.walsh@...>

On Thu, Feb 25, 2016 at 03:54:03PM -0500, Dmitriy Korovkin wrote:
Problem: there are two similar mechanisms in nanokernel: nano_timers and
nano_timeouts. In order to optimize codeand space it's better to have one
mechanism for both.

Proposal: Implement nano_timer through timeout mechanism. This
aproach allows to get rid of heavier nanokernel lifo component in
favor of more lightweight nanokernel timeout implementation.

The _nano_timeout structure gets two additional arguments: void
*user_data_ptr and bool expired, the flag that is set to true when
the timeout is expired.
I don't think you need this expired flag: delta_ticks_from_prev is
either 0 or -1 when the timeout expires (-1 I think).

_nano_timeout structure now can be safely renamed to nano_timer, as
it has everything required by nano_timer API.
I would prefer if we had a nano_timer object that is a wrapper around a
_nano_timeout, so that not all timeouts in the system are impacted in
size by this.

struct nano_timer {
struct _nano_timeout timeout;
void *user_data;

In this case, if a function like fiber_sleep() is invoked, the
user_data_ptr is set to NULL.
For the nano_timer API user_data_ptr is used to store the user data
pointer. When the nano_timer_init() function is called, it gets the
_nano_timer structure and initializes it as before. On the
nano_timer_start() call the nano_timer structure is being added to
the sorted list via _nano_timeout_add() function.
nano_timer_test() checks the expired flag of the nano_timer
structure. if it is true, the function just returns the
user_data_ptr, otherwise, if the timeout_in_ticks is not TICKS_NONE,
it puts the fiber or task to sleep by calling _Swap().

Question: is it needed to wait for a specified timeout, if
timeout_in_ticks argument is neither TICKS_NONE nor TICKS_UNLIMITED?
No. We consider that you only want to verify if the timeout has expired
by polling, or you want to wait for it to expire, which has a itself a

_nano_timeout_handle_one_timeout(), in turn, sets the expired flag
to true and if fiber or task is waiting, marks it runnable.
As stated above, I don't think you need the expired flag.

fiberRtnValueSet is used to set the return value to user_data_ptr.
I don't think you need to use fiberRtnValueSet: you will get the user
data back when you call nano_timer_test, which can just look in the
nano_timer object to retrieve the data.

Problem: in microkernel system clock ticks are processed in the
k_server fiber, which does not allow using timeouts during the
initialization before k_server fiber starts.

In order to allow using timeouts during the system initialization
_do_sys_clock_tick_announce pointer has to be modified to point at
the _nano_sys_clock_tick_announce() until the microkernel
_k_server() fiber starts. This way the _do_sys_clock_tick_announce
may be initialized as a pointer to
_nano_sys_clock_tick_announce() routine by default.

This modification needs to be done with changing priority of the
driver initialization routines that use timeout. Such routines need
to be invoked not on PRIMARY, but on NANOKERNEL initialization
I don't have a problem with this part of the proposal.


Benjamin Walsh, SMTS
Wind River Rocket
Zephyr kernel maintainer

Join { to automatically receive all group messages.