zephyr/doc/kernel/common/common_contexts.rst

102 lines
3.1 KiB
ReStructuredText

.. _common_contexts:
Execution Context Services
##########################
Concepts
********
Every kernel execution context has an associated *type* that indicates whether
the context is a task, a fiber, or the kernel's interrupt handling context.
All task and fiber contexts have a unique *thread identifier* value used to
uniquely identify them. Each task and fiber can also support a 32-bit *thread
custom data* value. This value is accessible only by the task or fiber itself,
and may be used by the application for any purpose. The default custom data
value for a task or fiber is zero.
.. note::
The custom data value is not available to ISRs because these operate
only within the shared kernel interrupt handling context.
The kernel permits a task or a fiber to perform a ``busy wait``, thus delaying
its processing for a specified time period. Such a delay occurs without
requiring the kernel to perform context switching, as it typically does with
timer and timeout services.
Purpose
*******
Use kernel execution context services when writing code that should
operate differently when it is executed by different contexts.
Use the ``busy wait`` service when the required delay is too short to
warrant context switching to another task or fiber. The ``busy wait``
service may also be used when performing a delay as part of the
nanokernel's background task in a nanokernel-only system; this task is
not allowed to voluntarily relinquish the CPU.
Usage
*****
Configuring Custom Data Support
===============================
Use the :option:`CONFIG_THREAD_CUSTOM_DATA` configuration option
to enable support for thread custom data. By default, custom data
support is disabled.
Example: Performing Execution Context-Specific Processing
=========================================================
This code shows how a routine can use a thread's custom data value
to limit the number of times a thread may call the routine. Note that
counting is not performed when the routine is called by an ISR; ISRs
do not have a custom data value.
.. note::
Obviously, only a single routine can use this technique
since it monopolizes the use of the custom data value.
.. code-block:: c
#define CALL_LIMIT 7
int call_tracking_routine(void)
{
uint32_t call_count;
if (sys_execution_context_type_get() != NANO_CTX_ISR) {
call_count = (uint32_t)sys_thread_custom_data_get();
if (call_count == CALL_LIMIT)
return -1;
call_count++;
sys_thread_custom_data_set((void *)call_count);
}
/* do rest of routine's processing */
...
}
APIs
****
The following kernel execution context APIs are common to both
:file:`microkernel.h` and :file:`nanokernel.h`:
:c:func:`sys_thread_self_get()`
Gets thread identifier of currently executing task or fiber.
:c:func:`sys_execution_context_type_get()`
Gets type of currently executing context (i.e. task, fiber, or ISR).
:c:func:`sys_thread_custom_data_set()`
Writes custom data for currently executing task or fiber.
:c:func:`sys_thread_custom_data_get()`
Reads custom data for currently executing task or fiber.