| .. _threads_v2: |
| |
| Threads |
| ####### |
| |
| .. note:: |
| There is also limited support for using :ref:`nothread`. |
| |
| .. contents:: |
| :local: |
| :depth: 2 |
| |
| This section describes kernel services for creating, scheduling, and deleting |
| independently executable threads of instructions. |
| |
| A :dfn:`thread` is a kernel object that is used for application processing |
| that is too lengthy or too complex to be performed by an ISR. |
| |
| Any number of threads can be defined by an application (limited only by |
| available RAM). Each thread is referenced by a :dfn:`thread id` that is assigned |
| when the thread is spawned. |
| |
| A thread has the following key properties: |
| |
| * A **stack area**, which is a region of memory used for the thread's stack. |
| The **size** of the stack area can be tailored to conform to the actual needs |
| of the thread's processing. Special macros exist to create and work with |
| stack memory regions. |
| |
| * A **thread control block** for private kernel bookkeeping of the thread's |
| metadata. This is an instance of type :c:struct:`k_thread`. |
| |
| * An **entry point function**, which is invoked when the thread is started. |
| Up to 3 **argument values** can be passed to this function. |
| |
| * A **scheduling priority**, which instructs the kernel's scheduler how to |
| allocate CPU time to the thread. (See :ref:`scheduling_v2`.) |
| |
| * A set of **thread options**, which allow the thread to receive special |
| treatment by the kernel under specific circumstances. |
| (See :ref:`thread_options_v2`.) |
| |
| * A **start delay**, which specifies how long the kernel should wait before |
| starting the thread. |
| |
| * An **execution mode**, which can either be supervisor or user mode. |
| By default, threads run in supervisor mode and allow access to |
| privileged CPU instructions, the entire memory address space, and |
| peripherals. User mode threads have a reduced set of privileges. |
| This depends on the :kconfig:option:`CONFIG_USERSPACE` option. See :ref:`usermode_api`. |
| |
| .. _lifecycle_v2: |
| |
| Lifecycle |
| *********** |
| |
| .. _spawning_thread: |
| |
| Thread Creation |
| =============== |
| |
| A thread must be created before it can be used. The kernel initializes |
| the thread control block as well as one end of the stack portion. The remainder |
| of the thread's stack is typically left uninitialized. |
| |
| Specifying a start delay of :c:macro:`K_NO_WAIT` instructs the kernel |
| to start thread execution immediately. Alternatively, the kernel can be |
| instructed to delay execution of the thread by specifying a timeout |
| value -- for example, to allow device hardware used by the thread |
| to become available. |
| |
| The kernel allows a delayed start to be canceled before the thread begins |
| executing. A cancellation request has no effect if the thread has already |
| started. A thread whose delayed start was successfully canceled must be |
| re-spawned before it can be used. |
| |
| Thread Termination |
| =================== |
| |
| Once a thread is started it typically executes forever. However, a thread may |
| synchronously end its execution by returning from its entry point function. |
| This is known as **termination**. |
| |
| A thread that terminates is responsible for releasing any shared resources |
| it may own (such as mutexes and dynamically allocated memory) |
| prior to returning, since the kernel does *not* reclaim them automatically. |
| |
| In some cases a thread may want to sleep until another thread terminates. |
| This can be accomplished with the :c:func:`k_thread_join` API. This |
| will block the calling thread until either the timeout expires, the target |
| thread self-exits, or the target thread aborts (either due to a |
| :c:func:`k_thread_abort` call or triggering a fatal error). |
| |
| Once a thread has terminated, the kernel guarantees that no use will |
| be made of the thread struct. The memory of such a struct can then be |
| re-used for any purpose, including spawning a new thread. Note that |
| the thread must be fully terminated, which presents race conditions |
| where a thread's own logic signals completion which is seen by another |
| thread before the kernel processing is complete. Under normal |
| circumstances, application code should use :c:func:`k_thread_join` or |
| :c:func:`k_thread_abort` to synchronize on thread termination state |
| and not rely on signaling from within application logic. |
| |
| Thread Aborting |
| =============== |
| |
| A thread may asynchronously end its execution by **aborting**. The kernel |
| automatically aborts a thread if the thread triggers a fatal error condition, |
| such as dereferencing a null pointer. |
| |
| A thread can also be aborted by another thread (or by itself) |
| by calling :c:func:`k_thread_abort`. However, it is typically preferable |
| to signal a thread to terminate itself gracefully, rather than aborting it. |
| |
| As with thread termination, the kernel does not reclaim shared resources |
| owned by an aborted thread. |
| |
| .. note:: |
| The kernel does not currently make any claims regarding an application's |
| ability to respawn a thread that aborts. |
| |
| Thread Suspension |
| ================== |
| |
| A thread can be prevented from executing for an indefinite period of time |
| if it becomes **suspended**. The function :c:func:`k_thread_suspend` |
| can be used to suspend any thread, including the calling thread. |
| Suspending a thread that is already suspended has no additional effect. |
| |
| Once suspended, a thread cannot be scheduled until another thread calls |
| :c:func:`k_thread_resume` to remove the suspension. |
| |
| .. note:: |
| A thread can prevent itself from executing for a specified period of time |
| using :c:func:`k_sleep`. However, this is different from suspending |
| a thread since a sleeping thread becomes executable automatically when the |
| time limit is reached. |
| |
| .. _thread_states: |
| |
| Thread States |
| ************* |
| |
| A thread that has no factors that prevent its execution is deemed |
| to be **ready**, and is eligible to be selected as the current thread. |
| |
| A thread that has one or more factors that prevent its execution |
| is deemed to be **unready**, and cannot be selected as the current thread. |
| |
| The following factors make a thread unready: |
| |
| * The thread has not been started. |
| * The thread is waiting for a kernel object to complete an operation. |
| (For example, the thread is taking a semaphore that is unavailable.) |
| * The thread is waiting for a timeout to occur. |
| * The thread has been suspended. |
| * The thread has terminated or aborted. |
| |
| .. image:: thread_states.svg |
| :align: center |
| |
| .. note:: |
| |
| Although the diagram above may appear to suggest that both **Ready** and |
| **Running** are distinct thread states, that is not the correct |
| interpretation. **Ready** is a thread state, and **Running** is a |
| schedule state that only applies to **Ready** threads. |
| |
| Thread Stack objects |
| ******************** |
| |
| Every thread requires its own stack buffer for the CPU to push context. |
| Depending on configuration, there are several constraints that must be |
| met: |
| |
| - There may need to be additional memory reserved for memory management |
| structures |
| - If guard-based stack overflow detection is enabled, a small write- |
| protected memory management region must immediately precede the stack buffer |
| to catch overflows. |
| - If userspace is enabled, a separate fixed-size privilege elevation stack must |
| be reserved to serve as a private kernel stack for handling system calls. |
| - If userspace is enabled, the thread's stack buffer must be appropriately |
| sized and aligned such that a memory protection region may be programmed |
| to exactly fit. |
| |
| The alignment constraints can be quite restrictive, for example some MPUs |
| require their regions to be of some power of two in size, and aligned to its |
| own size. |
| |
| Because of this, portable code can't simply pass an arbitrary character buffer |
| to :c:func:`k_thread_create`. Special macros exist to instantiate stacks, |
| prefixed with ``K_KERNEL_STACK`` and ``K_THREAD_STACK``. |
| |
| Kernel-only Stacks |
| ================== |
| |
| If it is known that a thread will never run in user mode, or the stack is |
| being used for special contexts like handling interrupts, it is best to |
| define stacks using the ``K_KERNEL_STACK`` macros. |
| |
| These stacks save memory because an MPU region will never need to be |
| programmed to cover the stack buffer itself, and the kernel will not need |
| to reserve additional room for the privilege elevation stack, or memory |
| management data structures which only pertain to user mode threads. |
| |
| Attempts from user mode to use stacks declared in this way will result in |
| a fatal error for the caller. |
| |
| If ``CONFIG_USERSPACE`` is not enabled, the set of ``K_THREAD_STACK`` macros |
| have an identical effect to the ``K_KERNEL_STACK`` macros. |
| |
| Thread stacks |
| ============= |
| |
| If it is known that a stack will need to host user threads, or if this |
| cannot be determined, define the stack with ``K_THREAD_STACK`` macros. |
| This may use more memory but the stack object is suitable for hosting |
| user threads. |
| |
| If ``CONFIG_USERSPACE`` is not enabled, the set of ``K_THREAD_STACK`` macros |
| have an identical effect to the ``K_KERNEL_STACK`` macros. |
| |
| .. _thread_priorities: |
| |
| Thread Priorities |
| ****************** |
| |
| A thread's priority is an integer value, and can be either negative or |
| non-negative. |
| Numerically lower priorities takes precedence over numerically higher values. |
| For example, the scheduler gives thread A of priority 4 *higher* priority |
| over thread B of priority 7; likewise thread C of priority -2 has higher |
| priority than both thread A and thread B. |
| |
| The scheduler distinguishes between two classes of threads, |
| based on each thread's priority. |
| |
| * A :dfn:`cooperative thread` has a negative priority value. |
| Once it becomes the current thread, a cooperative thread remains |
| the current thread until it performs an action that makes it unready. |
| |
| * A :dfn:`preemptible thread` has a non-negative priority value. |
| Once it becomes the current thread, a preemptible thread may be supplanted |
| at any time if a cooperative thread, or a preemptible thread of higher |
| or equal priority, becomes ready. |
| |
| |
| A thread's initial priority value can be altered up or down after the thread |
| has been started. Thus it is possible for a preemptible thread to become |
| a cooperative thread, and vice versa, by changing its priority. |
| |
| .. note:: |
| The scheduler does not make heuristic decisions to re-prioritize threads. |
| Thread priorities are set and changed only at the application's request. |
| |
| The kernel supports a virtually unlimited number of thread priority levels. |
| The configuration options :kconfig:option:`CONFIG_NUM_COOP_PRIORITIES` and |
| :kconfig:option:`CONFIG_NUM_PREEMPT_PRIORITIES` specify the number of priority |
| levels for each class of thread, resulting in the following usable priority |
| ranges: |
| |
| * cooperative threads: (-:kconfig:option:`CONFIG_NUM_COOP_PRIORITIES`) to -1 |
| * preemptive threads: 0 to (:kconfig:option:`CONFIG_NUM_PREEMPT_PRIORITIES` - 1) |
| |
| .. image:: priorities.svg |
| :align: center |
| |
| For example, configuring 5 cooperative priorities and 10 preemptive priorities |
| results in the ranges -5 to -1 and 0 to 9, respectively. |
| |
| .. _metairq_priorities: |
| |
| Meta-IRQ Priorities |
| =================== |
| |
| When enabled (see :kconfig:option:`CONFIG_NUM_METAIRQ_PRIORITIES`), there is a special |
| subclass of cooperative priorities at the highest (numerically lowest) |
| end of the priority space: meta-IRQ threads. These are scheduled |
| according to their normal priority, but also have the special ability |
| to preempt all other threads (and other meta-IRQ threads) at lower |
| priorities, even if those threads are cooperative and/or have taken a |
| scheduler lock. Meta-IRQ threads are still threads, however, |
| and can still be interrupted by any hardware interrupt. |
| |
| This behavior makes the act of unblocking a meta-IRQ thread (by any |
| means, e.g. creating it, calling k_sem_give(), etc.) into the |
| equivalent of a synchronous system call when done by a lower |
| priority thread, or an ARM-like "pended IRQ" when done from true |
| interrupt context. The intent is that this feature will be used to |
| implement interrupt "bottom half" processing and/or "tasklet" features |
| in driver subsystems. The thread, once woken, will be guaranteed to |
| run before the current CPU returns into application code. |
| |
| Unlike similar features in other OSes, meta-IRQ threads are true |
| threads and run on their own stack (which must be allocated normally), |
| not the per-CPU interrupt stack. Design work to enable the use of the |
| IRQ stack on supported architectures is pending. |
| |
| Note that because this breaks the promise made to cooperative |
| threads by the Zephyr API (namely that the OS won't schedule other |
| thread until the current thread deliberately blocks), it should be |
| used only with great care from application code. These are not simply |
| very high priority threads and should not be used as such. |
| |
| .. _thread_options_v2: |
| |
| Thread Options |
| *************** |
| |
| The kernel supports a small set of :dfn:`thread options` that allow a thread |
| to receive special treatment under specific circumstances. The set of options |
| associated with a thread are specified when the thread is spawned. |
| |
| A thread that does not require any thread option has an option value of zero. |
| A thread that requires a thread option specifies it by name, using the |
| :literal:`|` character as a separator if multiple options are needed |
| (i.e. combine options using the bitwise OR operator). |
| |
| The following thread options are supported. |
| |
| :c:macro:`K_ESSENTIAL` |
| This option tags the thread as an :dfn:`essential thread`. This instructs |
| the kernel to treat the termination or aborting of the thread as a fatal |
| system error. |
| |
| By default, the thread is not considered to be an essential thread. |
| |
| :c:macro:`K_SSE_REGS` |
| This x86-specific option indicate that the thread uses the CPU's |
| SSE registers. Also see :c:macro:`K_FP_REGS`. |
| |
| By default, the kernel does not attempt to save and restore the contents |
| of these registers when scheduling the thread. |
| |
| :c:macro:`K_FP_REGS` |
| This option indicate that the thread uses the CPU's floating point |
| registers. This instructs the kernel to take additional steps to save |
| and restore the contents of these registers when scheduling the thread. |
| (For more information see :ref:`float_v2`.) |
| |
| By default, the kernel does not attempt to save and restore the contents |
| of this register when scheduling the thread. |
| |
| :c:macro:`K_USER` |
| If :kconfig:option:`CONFIG_USERSPACE` is enabled, this thread will be created in |
| user mode and will have reduced privileges. See :ref:`usermode_api`. Otherwise |
| this flag does nothing. |
| |
| :c:macro:`K_INHERIT_PERMS` |
| If :kconfig:option:`CONFIG_USERSPACE` is enabled, this thread will inherit all |
| kernel object permissions that the parent thread had, except the parent |
| thread object. See :ref:`usermode_api`. |
| |
| |
| .. _custom_data_v2: |
| |
| Thread Custom Data |
| ****************** |
| |
| Every thread has a 32-bit :dfn:`custom data` area, accessible only by |
| the thread itself, and may be used by the application for any purpose |
| it chooses. The default custom data value for a thread is zero. |
| |
| .. note:: |
| Custom data support is not available to ISRs because they operate |
| within a single shared kernel interrupt handling context. |
| |
| By default, thread custom data support is disabled. The configuration option |
| :kconfig:option:`CONFIG_THREAD_CUSTOM_DATA` can be used to enable support. |
| |
| The :c:func:`k_thread_custom_data_set` and |
| :c:func:`k_thread_custom_data_get` functions are used to write and read |
| a thread's custom data, respectively. A thread can only access its own |
| custom data, and not that of another thread. |
| |
| The following code uses the custom data feature to record the number of times |
| each thread calls a specific routine. |
| |
| .. note:: |
| Obviously, only a single routine can use this technique, |
| since it monopolizes the use of the custom data feature. |
| |
| .. code-block:: c |
| |
| int call_tracking_routine(void) |
| { |
| uint32_t call_count; |
| |
| if (k_is_in_isr()) { |
| /* ignore any call made by an ISR */ |
| } else { |
| call_count = (uint32_t)k_thread_custom_data_get(); |
| call_count++; |
| k_thread_custom_data_set((void *)call_count); |
| } |
| |
| /* do rest of routine's processing */ |
| ... |
| } |
| |
| Use thread custom data to allow a routine to access thread-specific information, |
| by using the custom data as a pointer to a data structure owned by the thread. |
| |
| Implementation |
| ************** |
| |
| Spawning a Thread |
| ================= |
| |
| A thread is spawned by defining its stack area and its thread control block, |
| and then calling :c:func:`k_thread_create`. |
| |
| The stack area must be defined using :c:macro:`K_THREAD_STACK_DEFINE` or |
| :c:macro:`K_KERNEL_STACK_DEFINE` to ensure it is properly set up in memory. |
| |
| The size parameter for the stack must be one of three values: |
| |
| - The original requested stack size passed to |
| ``K_THREAD_STACK`` or ``K_KERNEL_STACK`` family of stack instantiation |
| macros. |
| - For a stack object defined with the ``K_THREAD_STACK`` family of |
| macros, the return value of :c:macro:`K_THREAD_STACK_SIZEOF()` for that' |
| object. |
| - For a stack object defined with the ``K_KERNEL_STACK`` family of |
| macros, the return value of :c:macro:`K_KERNEL_STACK_SIZEOF()` for that |
| object. |
| |
| The thread spawning function returns its thread id, which can be used |
| to reference the thread. |
| |
| The following code spawns a thread that starts immediately. |
| |
| .. code-block:: c |
| |
| #define MY_STACK_SIZE 500 |
| #define MY_PRIORITY 5 |
| |
| extern void my_entry_point(void *, void *, void *); |
| |
| K_THREAD_STACK_DEFINE(my_stack_area, MY_STACK_SIZE); |
| struct k_thread my_thread_data; |
| |
| k_tid_t my_tid = k_thread_create(&my_thread_data, my_stack_area, |
| K_THREAD_STACK_SIZEOF(my_stack_area), |
| my_entry_point, |
| NULL, NULL, NULL, |
| MY_PRIORITY, 0, K_NO_WAIT); |
| |
| Alternatively, a thread can be declared at compile time by calling |
| :c:macro:`K_THREAD_DEFINE`. Observe that the macro defines |
| the stack area, control block, and thread id variables automatically. |
| |
| The following code has the same effect as the code segment above. |
| |
| .. code-block:: c |
| |
| #define MY_STACK_SIZE 500 |
| #define MY_PRIORITY 5 |
| |
| extern void my_entry_point(void *, void *, void *); |
| |
| K_THREAD_DEFINE(my_tid, MY_STACK_SIZE, |
| my_entry_point, NULL, NULL, NULL, |
| MY_PRIORITY, 0, 0); |
| |
| .. note:: |
| The delay parameter to :c:func:`k_thread_create` is a |
| :c:type:`k_timeout_t` value, so :c:macro:`K_NO_WAIT` means to start the |
| thread immediately. The corresponding parameter to :c:macro:`K_THREAD_DEFINE` |
| is a duration in integral milliseconds, so the equivalent argument is 0. |
| |
| User Mode Constraints |
| --------------------- |
| |
| This section only applies if :kconfig:option:`CONFIG_USERSPACE` is enabled, and a user |
| thread tries to create a new thread. The :c:func:`k_thread_create` API is |
| still used, but there are additional constraints which must be met or the |
| calling thread will be terminated: |
| |
| * The calling thread must have permissions granted on both the child thread |
| and stack parameters; both are tracked by the kernel as kernel objects. |
| |
| * The child thread and stack objects must be in an uninitialized state, |
| i.e. it is not currently running and the stack memory is unused. |
| |
| * The stack size parameter passed in must be equal to or less than the |
| bounds of the stack object when it was declared. |
| |
| * The :c:macro:`K_USER` option must be used, as user threads can only create |
| other user threads. |
| |
| * The :c:macro:`K_ESSENTIAL` option must not be used, user threads may not be |
| considered essential threads. |
| |
| * The priority of the child thread must be a valid priority value, and equal to |
| or lower than the parent thread. |
| |
| Dropping Permissions |
| ==================== |
| |
| If :kconfig:option:`CONFIG_USERSPACE` is enabled, a thread running in supervisor mode |
| may perform a one-way transition to user mode using the |
| :c:func:`k_thread_user_mode_enter` API. This is a one-way operation which |
| will reset and zero the thread's stack memory. The thread will be marked |
| as non-essential. |
| |
| Terminating a Thread |
| ==================== |
| |
| A thread terminates itself by returning from its entry point function. |
| |
| The following code illustrates the ways a thread can terminate. |
| |
| .. code-block:: c |
| |
| void my_entry_point(int unused1, int unused2, int unused3) |
| { |
| while (1) { |
| ... |
| if (<some condition>) { |
| return; /* thread terminates from mid-entry point function */ |
| } |
| ... |
| } |
| |
| /* thread terminates at end of entry point function */ |
| } |
| |
| If :kconfig:option:`CONFIG_USERSPACE` is enabled, aborting a thread will additionally |
| mark the thread and stack objects as uninitialized so that they may be re-used. |
| |
| Runtime Statistics |
| ****************** |
| |
| Thread runtime statistics can be gathered and retrieved if |
| :kconfig:option:`CONFIG_THREAD_RUNTIME_STATS` is enabled, for example, total number of |
| execution cycles of a thread. |
| |
| By default, the runtime statistics are gathered using the default kernel |
| timer. For some architectures, SoCs or boards, there are timers with higher |
| resolution available via timing functions. Using of these timers can be |
| enabled via :kconfig:option:`CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS`. |
| |
| Here is an example: |
| |
| .. code-block:: c |
| |
| k_thread_runtime_stats_t rt_stats_thread; |
| |
| k_thread_runtime_stats_get(k_current_get(), &rt_stats_thread); |
| |
| printk("Cycles: %llu\n", rt_stats_thread.execution_cycles); |
| |
| Suggested Uses |
| ************** |
| |
| Use threads to handle processing that cannot be handled in an ISR. |
| |
| Use separate threads to handle logically distinct processing operations |
| that can execute in parallel. |
| |
| |
| Configuration Options |
| ********************** |
| |
| Related configuration options: |
| |
| * :kconfig:option:`CONFIG_MAIN_THREAD_PRIORITY` |
| * :kconfig:option:`CONFIG_MAIN_STACK_SIZE` |
| * :kconfig:option:`CONFIG_IDLE_STACK_SIZE` |
| * :kconfig:option:`CONFIG_THREAD_CUSTOM_DATA` |
| * :kconfig:option:`CONFIG_NUM_COOP_PRIORITIES` |
| * :kconfig:option:`CONFIG_NUM_PREEMPT_PRIORITIES` |
| * :kconfig:option:`CONFIG_TIMESLICING` |
| * :kconfig:option:`CONFIG_TIMESLICE_SIZE` |
| * :kconfig:option:`CONFIG_TIMESLICE_PRIORITY` |
| * :kconfig:option:`CONFIG_USERSPACE` |
| |
| |
| |
| API Reference |
| ************** |
| |
| .. doxygengroup:: thread_apis |
| |
| .. doxygengroup:: thread_stack_api |