| .. _lifecycle_v2: |
| |
| Lifecycle |
| ######### |
| |
| 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. |
| |
| .. contents:: |
| :local: |
| :depth: 2 |
| |
| Concepts |
| ******** |
| |
| Any number of threads can be defined by an application. 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:type:`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. |
| |
| .. _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. |
| |
| .. note:: |
| The kernel does not currently make any claims regarding an application's |
| ability to respawn a thread that terminates. |
| |
| 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 :cpp: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 :cpp: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 |
| :cpp:func:`k_thread_resume()` to remove the suspension. |
| |
| .. note:: |
| A thread can prevent itself from executing for a specified period of time |
| using :cpp: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_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_FP_REGS` and :c:macro:`K_SSE_REGS` |
| These x86-specific options indicate that the thread uses the CPU's |
| floating point registers and SSE registers, respectively. 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 these registers when scheduling the thread. |
| |
| Implementation |
| ************** |
| |
| Spawning a Thread |
| ================= |
| |
| A thread is spawned by defining its stack area and its thread control block, |
| and then calling :cpp:func:`k_thread_create()`. The stack area must be defined |
| using :c:macro:`K_THREAD_STACK_DEFINE` to ensure it is properly set up in |
| memory. |
| |
| 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 spawned 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, K_NO_WAIT); |
| |
| 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 */ |
| } |
| |
| |
| 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: |
| |
| * None. |
| |
| APIs |
| **** |
| |
| The following thread APIs are provided by :file:`kernel.h`: |
| |
| * :c:macro:`K_THREAD_DEFINE` |
| * :cpp:func:`k_thread_create()` |
| * :cpp:func:`k_thread_cancel()` |
| * :cpp:func:`k_thread_abort()` |
| * :cpp:func:`k_thread_suspend()` |
| * :cpp:func:`k_thread_resume()` |
| * :c:macro:`K_THREAD_STACK_DEFINE` |
| * :c:macro:`K_THREAD_STACK_ARRAY_DEFINE` |
| * :c:macro:`K_THREAD_STACK_MEMBER` |
| * :c:macro:`K_THREAD_STACK_SIZEOF` |
| * :c:macro:`K_THREAD_STACK_BUFFER` |