zephyr/doc/reference/terminology.rst
Peter Bigot 9f68178fe1 doc: reference: terminology: refine API attributes
The original description for isr-ok allowed the function to return an
error if called from an interrupt context, rather than doing its job.
This led to complex descriptions like "isr-ok but not sleep" to
indicate that the function could be called from thread or interrupt
context without visible behavior changes, including returning an
error based on calling context.

Remove the special terminology for cases where a function returns an
error (rather than causing undefined behavior) when invoked from an
interrupt or pre-kernel.  Redefine isr-ok to indicate that the call
does what it's supposed to do regardless of interrupt or thread
context, delegating the description of allowed behaviors to the API
documentation (which should explicitly note when it's allowed to fail
to perform in non-thread context).

This also makes more clear that isr-ok applies to functions regardless
of whether they can cause an invoking thread to context switch.

Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
2020-04-22 17:39:56 +02:00

200 lines
6.8 KiB
ReStructuredText

.. _api_terms:
API Terminology
###############
The following terms may be used as shorthand API tags to indicate the
allowed calling context (thread, ISR, pre-kernel), the effect of a call
on the current thread state, and other behavioral characteristics.
:ref:`api_term_reschedule`
if executing the function reaches a reschedule point
:ref:`api_term_sleep`
if executing the function can cause the invoking thread to sleep
:ref:`api_term_no-wait`
if a parameter to the function can prevent the invoking thread from
trying to sleep
:ref:`api_term_isr-ok`
if the function can be safely called and will have its specified
effect whether invoked from interrupt or thread context
:ref:`api_term_pre-kernel-ok`
if the function can be safely called before the kernel has been fully
initialized and will have its specified effect when invoked from that
context.
:ref:`api_term_async`
if the function may return before the operation it initializes is
complete (i.e. function return and operation completion are
asynchronous)
:ref:`api_term_supervisor`
if the calling thread must have supervisor privileges to execute the
function
Details on the behavioral impact of each attribute are in the following
sections.
.. _api_term_reschedule:
reschedule
==========
The reschedule attribute is used on a function that can reach a
:ref:`reschedule point <scheduling_v2>` within its execution.
Details
-------
The significance of this attribute is that when a rescheduling function
is invoked by a thread it is possible for that thread to be suspended as
a consequence of a higher-priority thread being made ready. Whether the
suspension actually occurs depends on the operation associated with the
reschedule point and the relative priorities of the invoking thread and
the head of the ready queue.
Note that in the case of timeslicing, or reschedule points executed from
interrupts, any thread may be suspended in any function.
Functions that are not **reschedule** may be invoked from either thread
or interrupt context.
Functions that are **reschedule** may be invoked from thread context.
Functions that are **reschedule** but not **sleep** may be invoked from
interrupt context.
.. _api_term_sleep:
sleep
=====
The sleep attribute is used on a function that can cause the invoking
thread to sleep.
Explanation
-----------
This attribute is of relevance specifically when considering
applications that use only non-preemptible threads, because the kernel
will not replace a running cooperative-only thread at a reschedule point
unless that thread has explicitly invoked an operation that caused it to
sleep.
This attribute does not imply the function will sleep unconditionally,
but that the operation may require an invoking thread that would have to
suspend, wait, or invoke :cpp:func:`k_yield()` before it can complete
its operation. This behavior may be mediated by **no-wait**.
Functions that are **sleep** are implicitly **reschedule**.
Functions that are **sleep** may be invoked from thread context.
Functions that are **sleep** may be invoked from interrupt and
pre-kernel contexts if and only if invoked in **no-wait** mode.
.. _api_term_no-wait:
no-wait
=======
The no-wait attribute is used on a function that is also **sleep** to
indicate that a parameter to the function can force an execution path
that will not cause the invoking thread to sleep.
Explanation
-----------
The paradigmatic case of a no-wait function is a function that takes a
timeout, to which :c:macro:`K_NO_WAIT` can be passed. The semantics of
this special timeout value are to execute the function's operation as
long as it can be completed immediately, and to return an error code
rather than sleep if it cannot.
It is use of the no-wait feature that allows functions like
:cpp:func:`k_sem_take` to be invoked from ISRs, since it is not
permitted to sleep in interrupt context.
A function with a no-wait path does not imply that taking that path
guarantees the function is synchronous.
Functions with this attribute may be invoked from interrupt and
pre-kernel contexts only when the parameter selects the no-wait path.
.. _api_term_isr-ok:
isr-ok
======
The isr-ok attribute is used on a function to indicate that it works
whether it is being invoked from interrupt or thread context.
Explanation
-----------
Any function that is not **sleep** is inherently **isr-ok**. Functions
that are **sleep** are **isr-ok** if the implementation ensures that the
documented behavior is implemented even if called from an interrupt
context. This may be achieved by having the implementation detect the
calling context and transfer the operation that would sleep to a thread,
or by documenting that when invoked from a non-thread context the
function will return a specific error (generally ``-EWOULDBLOCK``).
Note that a function that is **no-wait** is safe to call from interrupt
context only when the no-wait path is selected. **isr-ok** functions
need not provide a no-wait path.
.. _api_term_pre-kernel-ok:
pre-kernel-ok
=============
The pre-kernel-ok attribute is used on a function to indicate that it
works as documented even when invoked before the kernel main thread has
been started.
Explanation
-----------
This attribute is similar to **isr-ok** in function, but is intended for
use by any API that is expected to be called in :c:func:`DEVICE_INIT()`
or :c:func:`SYS_INIT()` calls that may be invoked with ``PRE_KERNEL_1``
or ``PRE_KERNEL_2`` initialization levels.
Generally a function that is **pre-kernel-ok** checks
:cpp:func:`k_is_pre_kernel` when determining whether it can fulfill its
required behavior. In many cases it would also check
:cpp:func:`k_is_in_isr` so it can be **isr-ok** as well.
.. _api_term_async:
async
=====
A function is **async** (i.e. asynchronous) if it may return before the
operation it initiates has completed. An asynchronous function will
generally provide a mechanism by which operation completion is reported,
e.g. a callback or event.
A function that is not asynchronous is synchronous, i.e. the operation
will always be complete when the function returns. As most functions
are synchronous this behavior does not have a distinct attribute to
identify it.
Explanation
-----------
Be aware that **async** is orthogonal to context-switching. Some APIs
may provide completion information through a callback, but may suspend
while waiting for the resource necessary to initiate the operation; an
example is :cpp:func:`spi_transceive_async`.
If a function is both **no-wait** and **async** then selecting the
no-wait path only guarantees that the function will not sleep. It does
not affect whether the operation will be completed before the function
returns.
.. _api_term_supervisor:
supervisor
==========
The supervisor attribute is relevant only in user-mode applications, and
indicates that the function cannot be invoked from user mode.