Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved documentation of relative timeouts in timer ISR context #59833

Merged
merged 2 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions doc/kernel/services/timing/clocks.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,23 @@ For example:

All these values are specified using a :c:struct:`k_timeout_t` value. This is
an opaque struct type that must be initialized using one of a family
of kernel timeout macros. The most common, :c:macro:`K_MSEC` , defines
a time in milliseconds after the current time (strictly: the time at
which the kernel receives the timeout value).
of kernel timeout macros. The most common, :c:macro:`K_MSEC`, defines
a time in milliseconds after the current time.

What is meant by "current time" for relative timeouts depends on the context:

* When scheduling a relative timeout from within a timeout callback (e.g. from
within the expiry function passed to :c:func:`k_timer_init` or the work handler
passed to :c:func:`k_work_init_delayable`), "current time" is the exact time at
which the currently firing timeout was originally scheduled even if the "real
time" will already have advanced. This is to ensure that timers scheduled from
within another timer's callback will always be calculated with a precise offset
to the firing timer. It is thereby possible to fire at regular intervals without
introducing systematic clock drift over time.

* When scheduling a timeout from application context, "current time" means the
value returned by :c:func:`k_uptime_ticks` at the time at which the kernel
receives the timeout value.

Other options for timeout initialization follow the unit conventions
described above: :c:macro:`K_NSEC()`, :c:macro:`K_USEC`, :c:macro:`K_TICKS` and
Expand Down
4 changes: 2 additions & 2 deletions include/zephyr/drivers/timer/system_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ extern "C" {
#endif

/**
* @brief Clock APIs
* @defgroup clock_apis Clock APIs
* @brief System Clock APIs
* @defgroup clock_apis System Clock APIs
* @{
*/

Expand Down
18 changes: 17 additions & 1 deletion kernel/timeout.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ static struct k_spinlock timeout_lock;
#define MAX_WAIT (IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE) \
? K_TICKS_FOREVER : INT_MAX)

/* Cycles left to process in the currently-executing sys_clock_announce() */
/* Ticks left to process in the currently-executing sys_clock_announce() */
static int announce_remaining;

#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
Expand Down Expand Up @@ -61,6 +61,22 @@ static void remove_timeout(struct _timeout *t)

static int32_t elapsed(void)
{
/* While sys_clock_announce() is executing, new relative timeouts will be
* scheduled relatively to the currently firing timeout's original tick
* value (=curr_tick) rather than relative to the current
* sys_clock_elapsed().
*
* This means that timeouts being scheduled from within timeout callbacks
* will be scheduled at well-defined offsets from the currently firing
* timeout.
*
* As a side effect, the same will happen if an ISR with higher priority
* preempts a timeout callback and schedules a timeout.
*
* The distinction is implemented by looking at announce_remaining which
* will be non-zero while sys_clock_announce() is executing and zero
* otherwise.
*/
return announce_remaining == 0 ? sys_clock_elapsed() : 0U;
}

Expand Down
Loading