Threads¶
This section describes kernel services for creating, scheduling, and deleting independently executable threads of instructions.
A 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 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
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 Scheduling.)
A set of thread options, which allow the thread to receive special treatment by the kernel under specific circumstances. (See Thread Options.)
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
CONFIG_USERSPACE
option. See User Mode.
Lifecycle¶
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 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.
In some cases a thread may want to sleep until another thread terminates.
This can be accomplished with the 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
k_thread_abort() call or triggering a fatal error).
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 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 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
k_thread_resume()
to remove the suspension.
Note
A thread can prevent itself from executing for a specified period of time
using 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¶
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.
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 aligment 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.
Becasue of this, portable code can’t simply pass an arbitrary character buffer
to 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¶
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 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 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.
The kernel supports a virtually unlimited number of thread priority levels.
The configuration options CONFIG_NUM_COOP_PRIORITIES
and
CONFIG_NUM_PREEMPT_PRIORITIES
specify the number of priority
levels for each class of thread, resulting in the following usable priority
ranges:
cooperative threads: (-
CONFIG_NUM_COOP_PRIORITIES
) to -1preemptive threads: 0 to (
CONFIG_NUM_PREEMPT_PRIORITIES
- 1)
For example, configuring 5 cooperative priorities and 10 preemptive priorities results in the ranges -5 to -1 and 0 to 9, respectively.
Thread Options¶
The kernel supports a small set of 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
|
character as a separator if multiple options are needed
(i.e. combine options using the bitwise OR operator).
The following thread options are supported.
K_ESSENTIAL
This option tags the thread as an 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.
K_SSE_REGS
This x86-specific option indicate that the thread uses the CPU’s SSE registers. Also see
K_FP_REGS
.By default, the kernel does not attempt to save and restore the contents of this register when scheduling the thread.
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 Floating Point Services.)
By default, the kernel does not attempt to save and restore the contents of this register when scheduling the thread.
K_USER
If
CONFIG_USERSPACE
is enabled, this thread will be created in user mode and will have reduced privileges. See User Mode. Otherwise this flag does nothing.K_INHERIT_PERMS
If
CONFIG_USERSPACE
is enabled, this thread will inherit all kernel object permissions that the parent thread had, except the parent thread object. See User Mode.
Thread Custom Data¶
Every thread has a 32-bit 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
CONFIG_THREAD_CUSTOM_DATA
can be used to enable support.
The k_thread_custom_data_set()
and
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.
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 k_thread_create()
.
The stack area must be defined using K_THREAD_STACK_DEFINE
or
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
orK_KERNEL_STACK
family of stack instantiation macros.For a stack object defined with the
K_THREAD_STACK
family of macros, the return value ofK_THREAD_STACK_SIZEOF()
for that’ object.For a stack object defined with the
K_KERNEL_STACK
family of macros, the return value ofK_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.
#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
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.
#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 k_thread_create()
is a
k_timeout_t
value, so K_NO_WAIT
means to start the
thread immediately. The corresponding parameter to K_THREAD_DEFINE
is a duration in integral milliseconds, so the equivalent argument is 0.
User Mode Constraints¶
This section only applies if CONFIG_USERSPACE
is enabled, and a user
thread tries to create a new thread. The 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
K_USER
option must be used, as user threads can only create other user threads.The
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 CONFIG_USERSPACE
is enabled, a thread running in supervisor mode
may perform a one-way transition to user mode using the
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.
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 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
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 CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS
.
Here is an example:
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:
API Reference¶
-
group
thread_apis
Defines
-
K_ESSENTIAL
¶ system thread that must not abort
-
K_FP_REGS
¶ FPU registers are managed by context switch.
This option indicates 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. No effect if
CONFIG_FPU_SHARING
is not enabled.
-
K_USER
¶ user mode thread
This thread has dropped from supervisor mode to user mode and consequently has additional restrictions
-
K_INHERIT_PERMS
¶ Inherit Permissions.
Indicates that the thread being created should inherit all kernel object permissions from the thread that created it. No effect if
CONFIG_USERSPACE
is not enabled.
-
k_thread_access_grant
(thread, ...)¶ Grant a thread access to a set of kernel objects.
This is a convenience function. For the provided thread, grant access to the remaining arguments, which must be pointers to kernel objects.
The thread object must be initialized (i.e. running). The objects don’t need to be. Note that NULL shouldn’t be passed as an argument.
- Parameters
thread
: Thread to grant access to objects...
: list of kernel object pointers
-
K_THREAD_DEFINE
(name, stack_size, entry, p1, p2, p3, prio, options, delay)¶ Statically define and initialize a thread.
The thread may be scheduled for immediate execution or a delayed start.
Thread options are architecture-specific, and can include K_ESSENTIAL, K_FP_REGS, and K_SSE_REGS. Multiple options may be specified by separating them using “|” (the logical OR operator).
The ID of the thread can be accessed using:
extern const k_tid_t <name>;
- Parameters
name
: Name of the thread.stack_size
: Stack size in bytes.entry
: Thread entry function.p1
: 1st entry point parameter.p2
: 2nd entry point parameter.p3
: 3rd entry point parameter.prio
: Thread priority.options
: Thread options.delay
: Scheduling delay (in milliseconds), zero for no delay.
-
K_WORK_DEFINE
(work, work_handler)¶ Initialize a statically-defined work item.
This macro can be used to initialize a statically-defined workqueue work item, prior to its first use. For example,
static K_WORK_DEFINE(<work>, <work_handler>);
- Parameters
work
: Symbol name for work item objectwork_handler
: Function to invoke each time work item is processed.
-
K_DELAYED_WORK_DEFINE
(work, work_handler)¶ Initialize a statically-defined delayed work item.
This macro can be used to initialize a statically-defined workqueue delayed work item, prior to its first use. For example,
static K_DELAYED_WORK_DEFINE(<work>, <work_handler>);
- Parameters
work
: Symbol name for delayed work item objectwork_handler
: Function to invoke each time work item is processed.
Typedefs
-
typedef void (*
k_work_handler_t
)(struct k_work *work)¶ Work item handler function type.
A work item’s handler function is executed by a workqueue’s thread when the work item is processed by the workqueue.
- Return
N/A
- Parameters
work
: Address of the work item.
Functions
-
void
k_thread_foreach
(k_thread_user_cb_t user_cb, void *user_data)¶ Iterate over all the threads in the system.
This routine iterates over all the threads in the system and calls the user_cb function for each thread.
- Note
CONFIG_THREAD_MONITOR
must be set for this function to be effective.- Note
This API uses k_spin_lock to protect the _kernel.threads list which means creation of new threads and terminations of existing threads are blocked until this API returns.
- Return
N/A
- Parameters
user_cb
: Pointer to the user callback function.user_data
: Pointer to user data.
-
void
k_thread_foreach_unlocked
(k_thread_user_cb_t user_cb, void *user_data)¶ Iterate over all the threads in the system without locking.
This routine works exactly the same like k_thread_foreach but unlocks interrupts when user_cb is executed.
- Note
CONFIG_THREAD_MONITOR
must be set for this function to be effective.- Note
This API uses k_spin_lock only when accessing the _kernel.threads queue elements. It unlocks it during user callback function processing. If a new task is created when this
foreach
function is in progress, the added new task would not be included in the enumeration. If a task is aborted during this enumeration, there would be a race here and there is a possibility that this aborted task would be included in the enumeration.- Note
If the task is aborted and the memory occupied by its
k_thread
structure is reused when thisk_thread_foreach_unlocked
is in progress it might even lead to the system behave unstable. This function may never return, as it would follow somenext
task pointers treating given pointer as a pointer to the k_thread structure while it is something different right now. Do not reuse the memory that was occupied by k_thread structure of aborted task if it was aborted after this function was called in any context.- Parameters
user_cb
: Pointer to the user callback function.user_data
: Pointer to user data.
-
k_tid_t
k_thread_create
(struct k_thread *new_thread, k_thread_stack_t *stack, size_t stack_size, k_thread_entry_t entry, void *p1, void *p2, void *p3, int prio, uint32_t options, k_timeout_t delay)¶ Create a thread.
This routine initializes a thread, then schedules it for execution.
The new thread may be scheduled for immediate execution or a delayed start. If the newly spawned thread does not have a delayed start the kernel scheduler may preempt the current thread to allow the new thread to execute.
Thread options are architecture-specific, and can include K_ESSENTIAL, K_FP_REGS, and K_SSE_REGS. Multiple options may be specified by separating them using “|” (the logical OR operator).
Stack objects passed to this function must be originally defined with either of these macros in order to be portable:
K_THREAD_STACK_DEFINE() - For stacks that may support either user or supervisor threads.
K_KERNEL_STACK_DEFINE() - For stacks that may support supervisor threads only. These stacks use less memory if CONFIG_USERSPACE is enabled.
The stack_size parameter has constraints. It must either be:
The original size value passed to K_THREAD_STACK_DEFINE() or K_KERNEL_STACK_DEFINE()
The return value of K_THREAD_STACK_SIZEOF(stack) if the stack was defined with K_THREAD_STACK_DEFINE()
The return value of K_KERNEL_STACK_SIZEOF(stack) if the stack was defined with K_KERNEL_STACK_DEFINE().
Using other values, or sizeof(stack) may produce undefined behavior.
- Return
ID of new thread.
- Parameters
new_thread
: Pointer to uninitialized struct k_threadstack
: Pointer to the stack space.stack_size
: Stack size in bytes.entry
: Thread entry function.p1
: 1st entry point parameter.p2
: 2nd entry point parameter.p3
: 3rd entry point parameter.prio
: Thread priority.options
: Thread options.delay
: Scheduling delay, or K_NO_WAIT (for no delay).
-
FUNC_NORETURN void
k_thread_user_mode_enter
(k_thread_entry_t entry, void *p1, void *p2, void *p3)¶ Drop a thread’s privileges permanently to user mode.
This allows a supervisor thread to be re-used as a user thread. This function does not return, but control will transfer to the provided entry point as if this was a new user thread.
The implementation ensures that the stack buffer contents are erased. Any thread-local storage will be reverted to a pristine state.
Memory domain membership, resource pool assignment, kernel object permissions, priority, and thread options are preserved.
A common use of this function is to re-use the main thread as a user thread once all supervisor mode-only tasks have been completed.
- Parameters
entry
: Function to start executing fromp1
: 1st entry point parameterp2
: 2nd entry point parameterp3
: 3rd entry point parameter
-
static inline void
k_thread_heap_assign
(struct k_thread *thread, struct k_heap *heap)¶ Assign a resource memory pool to a thread.
By default, threads have no resource pool assigned unless their parent thread has a resource pool, in which case it is inherited. Multiple threads may be assigned to the same memory pool.
Changing a thread’s resource pool will not migrate allocations from the previous pool.
- Parameters
thread
: Target thread to assign a memory pool for resource requests.heap
: Heap object to use for resources, or NULL if the thread should no longer have a memory pool.
-
void
k_thread_system_pool_assign
(struct k_thread *thread)¶ Assign the system heap as a thread’s resource pool.
Similar to z_thread_resource_pool_assign(), but the thread will use the kernel heap to draw memory.
Use with caution, as a malicious thread could perform DoS attacks on the kernel heap.
- Parameters
thread
: Target thread to assign the system heap for resource requests
-
int
k_thread_join
(struct k_thread *thread, k_timeout_t timeout)¶ Sleep until a thread exits.
The caller will be put to sleep until the target thread exits, either due to being aborted, self-exiting, or taking a fatal error. This API returns immediately if the thread isn’t running.
This API may only be called from ISRs with a K_NO_WAIT timeout.
- Parameters
thread
: Thread to wait to exittimeout
: upper bound time to wait for the thread to exit.
- Return Value
0
: success, target thread has exited or wasn’t running-EBUSY
: returned without waiting-EAGAIN
: waiting period timed out-EDEADLK
: target thread is joining on the caller, or target thread is the caller
-
int32_t
k_sleep
(k_timeout_t timeout)¶ Put the current thread to sleep.
This routine puts the current thread to sleep for duration, specified as a k_timeout_t object.
- Note
if timeout is set to K_FOREVER then the thread is suspended.
- Return
Zero if the requested time has elapsed or the number of milliseconds left to sleep, if thread was woken up by k_wakeup call.
- Parameters
timeout
: Desired duration of sleep.
-
static inline int32_t
k_msleep
(int32_t ms)¶ Put the current thread to sleep.
This routine puts the current thread to sleep for duration milliseconds.
- Return
Zero if the requested time has elapsed or the number of milliseconds left to sleep, if thread was woken up by k_wakeup call.
- Parameters
ms
: Number of milliseconds to sleep.
-
int32_t
k_usleep
(int32_t us)¶ Put the current thread to sleep with microsecond resolution.
This function is unlikely to work as expected without kernel tuning. In particular, because the lower bound on the duration of a sleep is the duration of a tick,
CONFIG_SYS_CLOCK_TICKS_PER_SEC
must be adjusted to achieve the resolution desired. The implications of doing this must be understood before attempting to use k_usleep(). Use with caution.- Return
Zero if the requested time has elapsed or the number of microseconds left to sleep, if thread was woken up by k_wakeup call.
- Parameters
us
: Number of microseconds to sleep.
-
void
k_busy_wait
(uint32_t usec_to_wait)¶ Cause the current thread to busy wait.
This routine causes the current thread to execute a “do nothing” loop for usec_to_wait microseconds.
- Note
The clock used for the microsecond-resolution delay here may be skewed relative to the clock used for system timeouts like k_sleep(). For example k_busy_wait(1000) may take slightly more or less time than k_sleep(K_MSEC(1)), with the offset dependent on clock tolerances.
- Return
N/A
-
void
k_yield
(void)¶ Yield the current thread.
This routine causes the current thread to yield execution to another thread of the same or higher priority. If there are no other ready threads of the same or higher priority, the routine returns immediately.
- Return
N/A
-
void
k_wakeup
(k_tid_t thread)¶ Wake up a sleeping thread.
This routine prematurely wakes up thread from sleeping.
If thread is not currently sleeping, the routine has no effect.
- Return
N/A
- Parameters
thread
: ID of thread to wake.
-
k_tid_t
k_current_get
(void)¶ Get thread ID of the current thread.
- Return
ID of current thread.
-
void
k_thread_abort
(k_tid_t thread)¶ Abort a thread.
This routine permanently stops execution of thread. The thread is taken off all kernel queues it is part of (i.e. the ready queue, the timeout queue, or a kernel object wait queue). However, any kernel resources the thread might currently own (such as mutexes or memory blocks) are not released. It is the responsibility of the caller of this routine to ensure all necessary cleanup is performed.
- Return
N/A
- Parameters
thread
: ID of thread to abort.
-
void
k_thread_start
(k_tid_t thread)¶ Start an inactive thread.
If a thread was created with K_FOREVER in the delay parameter, it will not be added to the scheduling queue until this function is called on it.
- Parameters
thread
: thread to start
-
k_ticks_t
k_thread_timeout_expires_ticks
(struct k_thread *t)¶ Get time when a thread wakes up, in system ticks.
This routine computes the system uptime when a waiting thread next executes, in units of system ticks. If the thread is not waiting, it returns current system time.
-
k_ticks_t
k_thread_timeout_remaining_ticks
(struct k_thread *t)¶ Get time remaining before a thread wakes up, in system ticks.
This routine computes the time remaining before a waiting thread next executes, in units of system ticks. If the thread is not waiting, it returns zero.
-
int
k_thread_priority_get
(k_tid_t thread)¶ Get a thread’s priority.
This routine gets the priority of thread.
- Return
Priority of thread.
- Parameters
thread
: ID of thread whose priority is needed.
-
void
k_thread_priority_set
(k_tid_t thread, int prio)¶ Set a thread’s priority.
This routine immediately changes the priority of thread.
Rescheduling can occur immediately depending on the priority thread is set to:
If its priority is raised above the priority of the caller of this function, and the caller is preemptible, thread will be scheduled in.
If the caller operates on itself, it lowers its priority below that of other threads in the system, and the caller is preemptible, the thread of highest priority will be scheduled in.
Priority can be assigned in the range of -CONFIG_NUM_COOP_PRIORITIES to CONFIG_NUM_PREEMPT_PRIORITIES-1, where -CONFIG_NUM_COOP_PRIORITIES is the highest priority.
- Warning
Changing the priority of a thread currently involved in mutex priority inheritance may result in undefined behavior.
- Return
N/A
- Parameters
thread
: ID of thread whose priority is to be set.prio
: New priority.
-
void
k_thread_deadline_set
(k_tid_t thread, int deadline)¶ Set deadline expiration time for scheduler.
This sets the “deadline” expiration as a time delta from the current time, in the same units used by k_cycle_get_32(). The scheduler (when deadline scheduling is enabled) will choose the next expiring thread when selecting between threads at the same static priority. Threads at different priorities will be scheduled according to their static priority.
- Note
Deadlines are stored internally using 32 bit unsigned integers. The number of cycles between the “first” deadline in the scheduler queue and the “last” deadline must be less than 2^31 (i.e a signed non-negative quantity). Failure to adhere to this rule may result in scheduled threads running in an incorrect dealine order.
- Note
Despite the API naming, the scheduler makes no guarantees the the thread WILL be scheduled within that deadline, nor does it take extra metadata (like e.g. the “runtime” and “period” parameters in Linux sched_setattr()) that allows the kernel to validate the scheduling for achievability. Such features could be implemented above this call, which is simply input to the priority selection logic.
- Note
You should enable
CONFIG_SCHED_DEADLINE
in your project configuration.- Parameters
thread
: A thread on which to set the deadlinedeadline
: A time delta, in cycle units
-
int
k_thread_cpu_mask_clear
(k_tid_t thread)¶ Sets all CPU enable masks to zero.
After this returns, the thread will no longer be schedulable on any CPUs. The thread must not be currently runnable.
- Note
You should enable
CONFIG_SCHED_DEADLINE
in your project configuration.- Return
Zero on success, otherwise error code
- Parameters
thread
: Thread to operate upon
-
int
k_thread_cpu_mask_enable_all
(k_tid_t thread)¶ Sets all CPU enable masks to one.
After this returns, the thread will be schedulable on any CPU. The thread must not be currently runnable.
- Note
You should enable
CONFIG_SCHED_DEADLINE
in your project configuration.- Return
Zero on success, otherwise error code
- Parameters
thread
: Thread to operate upon
-
int
k_thread_cpu_mask_enable
(k_tid_t thread, int cpu)¶ Enable thread to run on specified CPU.
The thread must not be currently runnable.
- Note
You should enable
CONFIG_SCHED_DEADLINE
in your project configuration.- Return
Zero on success, otherwise error code
- Parameters
thread
: Thread to operate uponcpu
: CPU index
-
int
k_thread_cpu_mask_disable
(k_tid_t thread, int cpu)¶ Prevent thread to run on specified CPU.
The thread must not be currently runnable.
- Note
You should enable
CONFIG_SCHED_DEADLINE
in your project configuration.- Return
Zero on success, otherwise error code
- Parameters
thread
: Thread to operate uponcpu
: CPU index
-
void
k_thread_suspend
(k_tid_t thread)¶ Suspend a thread.
This routine prevents the kernel scheduler from making thread the current thread. All other internal operations on thread are still performed; for example, kernel objects it is waiting on are still handed to it. Note that any existing timeouts (e.g. k_sleep(), or a timeout argument to k_sem_take() et. al.) will be canceled. On resume, the thread will begin running immediately and return from the blocked call.
If thread is already suspended, the routine has no effect.
- Return
N/A
- Parameters
thread
: ID of thread to suspend.
-
void
k_thread_resume
(k_tid_t thread)¶ Resume a suspended thread.
This routine allows the kernel scheduler to make thread the current thread, when it is next eligible for that role.
If thread is not currently suspended, the routine has no effect.
- Return
N/A
- Parameters
thread
: ID of thread to resume.
-
void
k_sched_time_slice_set
(int32_t slice, int prio)¶ Set time-slicing period and scope.
This routine specifies how the scheduler will perform time slicing of preemptible threads.
To enable time slicing, slice must be non-zero. The scheduler ensures that no thread runs for more than the specified time limit before other threads of that priority are given a chance to execute. Any thread whose priority is higher than prio is exempted, and may execute as long as desired without being preempted due to time slicing.
Time slicing only limits the maximum amount of time a thread may continuously execute. Once the scheduler selects a thread for execution, there is no minimum guaranteed time the thread will execute before threads of greater or equal priority are scheduled.
When the current thread is the only one of that priority eligible for execution, this routine has no effect; the thread is immediately rescheduled after the slice period expires.
To disable timeslicing, set both slice and prio to zero.
- Return
N/A
- Parameters
slice
: Maximum time slice length (in milliseconds).prio
: Highest thread priority level eligible for time slicing.
-
void
k_sched_lock
(void)¶ Lock the scheduler.
This routine prevents the current thread from being preempted by another thread by instructing the scheduler to treat it as a cooperative thread. If the thread subsequently performs an operation that makes it unready, it will be context switched out in the normal manner. When the thread again becomes the current thread, its non-preemptible status is maintained.
This routine can be called recursively.
- Note
k_sched_lock() and k_sched_unlock() should normally be used when the operation being performed can be safely interrupted by ISRs. However, if the amount of processing involved is very small, better performance may be obtained by using irq_lock() and irq_unlock().
- Return
N/A
-
void
k_sched_unlock
(void)¶ Unlock the scheduler.
This routine reverses the effect of a previous call to k_sched_lock(). A thread must call the routine once for each time it called k_sched_lock() before the thread becomes preemptible.
- Return
N/A
-
void
k_thread_custom_data_set
(void *value)¶ Set current thread’s custom data.
This routine sets the custom data for the current thread to @ value.
Custom data is not used by the kernel itself, and is freely available for a thread to use as it sees fit. It can be used as a framework upon which to build thread-local storage.
- Return
N/A
- Parameters
value
: New custom data value.
-
void *
k_thread_custom_data_get
(void)¶ Get current thread’s custom data.
This routine returns the custom data for the current thread.
- Return
Current custom data value.
-
int
k_thread_name_set
(k_tid_t thread_id, const char *value)¶ Set current thread name.
Set the name of the thread to be used when
CONFIG_THREAD_MONITOR
is enabled for tracing and debugging.- Parameters
thread_id
: Thread to set name, or NULL to set the current threadvalue
: Name string
- Return Value
0
: on success-EFAULT
: Memory access error with supplied string-ENOSYS
: Thread name configuration option not enabled-EINVAL
: Thread name too long
-
const char *
k_thread_name_get
(k_tid_t thread_id)¶ Get thread name.
Get the name of a thread
- Parameters
thread_id
: Thread ID
- Return Value
Thread
: name, or NULL if configuration not enabled
-
int
k_thread_name_copy
(k_tid_t thread_id, char *buf, size_t size)¶ Copy the thread name into a supplied buffer.
- Parameters
thread_id
: Thread to obtain name informationbuf
: Destination buffersize
: Destination buffer size
- Return Value
-ENOSPC
: Destination buffer too small-EFAULT
: Memory access error-ENOSYS
: Thread name feature not enabled0
: Success
-
const char *
k_thread_state_str
(k_tid_t thread_id)¶ Get thread state string.
Get the human friendly thread state string
- Parameters
thread_id
: Thread ID
- Return Value
Thread
: state string, empty if no state flag is set
-
static inline void
k_work_init
(struct k_work *work, k_work_handler_t handler)¶ Initialize a work item.
This routine initializes a workqueue work item, prior to its first use.
- Return
N/A
- Parameters
work
: Address of work item.handler
: Function to invoke each time work item is processed.
-
static inline void
k_work_submit_to_queue
(struct k_work_q *work_q, struct k_work *work)¶ Submit a work item.
This routine submits work item
work
to be processed by workqueuework_q
. If the work item is already pending inwork_q
or any other workqueue as a result of an earlier submission, this routine has no effect on the work item. If the work item has already been processed, or is currently being processed, its work is considered complete and the work item can be resubmitted.- Warning
A submitted work item must not be modified until it has been processed by the workqueue.
- Note
Can be called by ISRs.
- Return
N/A
- Parameters
work_q
: Address of workqueue.work
: Address of work item.
-
static inline int
k_work_submit_to_user_queue
(struct k_work_q *work_q, struct k_work *work)¶ Submit a work item to a user mode workqueue.
Submits a work item to a workqueue that runs in user mode. A temporary memory allocation is made from the caller’s resource pool which is freed once the worker thread consumes the k_work item. The workqueue thread must have memory access to the k_work item being submitted. The caller must have permission granted on the work_q parameter’s queue object.
Otherwise this works the same as k_work_submit_to_queue().
- Note
Can be called by ISRs.
- Parameters
work_q
: Address of workqueue.work
: Address of work item.
- Return Value
-EBUSY
: if the work item was already in some workqueue-ENOMEM
: if no memory for thread resource pool allocation0
: Success
-
static inline bool
k_work_pending
(struct k_work *work)¶ Check if a work item is pending.
This routine indicates if work item work is pending in a workqueue’s queue.
- Note
Checking if the work is pending gives no guarantee that the work will still be pending when this information is used. It is up to the caller to make sure that this information is used in a safe manner.
- Note
Can be called by ISRs.
- Return
true if work item is pending, or false if it is not pending.
- Parameters
work
: Address of work item.
-
bool
k_delayed_work_pending
(struct k_delayed_work *work)¶ Check if a delayed work item is pending.
This routine indicates if the work item work is pending in a workqueue’s queue or waiting for the delay timeout.
- Note
Checking if the delayed work is pending gives no guarantee that the work will still be pending when this information is used. It is up to the caller to make sure that this information is used in a safe manner.
- Note
Can be called by ISRs.
- Return
true if work item is waiting for the delay to expire or pending on a work queue, or false if it is not pending.
- Parameters
work
: Address of delayed work item.
-
void
k_work_q_start
(struct k_work_q *work_q, k_thread_stack_t *stack, size_t stack_size, int prio)¶ Start a workqueue.
This routine starts workqueue work_q. The workqueue spawns its work processing thread, which runs forever.
- Return
N/A
- Parameters
work_q
: Address of workqueue.stack
: Pointer to work queue thread’s stack space, as defined by K_THREAD_STACK_DEFINE()stack_size
: Size of the work queue thread’s stack (in bytes), which should either be the same constant passed to K_THREAD_STACK_DEFINE() or the value of K_THREAD_STACK_SIZEOF().prio
: Priority of the work queue’s thread.
-
void
k_work_q_user_start
(struct k_work_q *work_q, k_thread_stack_t *stack, size_t stack_size, int prio)¶ Start a workqueue in user mode.
This works identically to k_work_q_start() except it is callable from user mode, and the worker thread created will run in user mode. The caller must have permissions granted on both the work_q parameter’s thread and queue objects, and the same restrictions on priority apply as k_thread_create().
- Return
N/A
- Parameters
work_q
: Address of workqueue.stack
: Pointer to work queue thread’s stack space, as defined by K_THREAD_STACK_DEFINE()stack_size
: Size of the work queue thread’s stack (in bytes), which should either be the same constant passed to K_THREAD_STACK_DEFINE() or the value of K_THREAD_STACK_SIZEOF().prio
: Priority of the work queue’s thread.
-
static inline void
k_delayed_work_init
(struct k_delayed_work *work, k_work_handler_t handler)¶ Initialize a delayed work item.
This routine initializes a workqueue delayed work item, prior to its first use.
- Return
N/A
- Parameters
work
: Address of delayed work item.handler
: Function to invoke each time work item is processed.
-
int
k_delayed_work_submit_to_queue
(struct k_work_q *work_q, struct k_delayed_work *work, k_timeout_t delay)¶ Submit a delayed work item.
This routine schedules work item work to be processed by workqueue work_q after a delay of delay milliseconds. The routine initiates an asynchronous countdown for the work item and then returns to the caller. Only when the countdown completes is the work item actually submitted to the workqueue and becomes pending.
Submitting a previously submitted delayed work item that is still counting down or is pending cancels the existing submission and restarts the countdown using the new delay. Note that this behavior is inherently subject to race conditions with the pre-existing timeouts and work queue, so care must be taken to synchronize such resubmissions externally.
Attempts to submit a work item to a queue after it has been submitted to a different queue will fail with
-EALREADY
until k_delayed_work_cancel() is successfully invoked on the work item to clear its internal state.- Warning
A delayed work item must not be modified until it has been processed by the workqueue.
- Note
Can be called by ISRs.
- Parameters
work_q
: Address of workqueue.work
: Address of delayed work item.delay
: Delay before submitting the work item
- Return Value
0
: Work item countdown started.-EINVAL
:if a previously submitted work item had to be cancelled and the cancellation failed; or
Work item is being processed or has completed its work.
-EADDRINUSE
: Work item was submitted to a different workqueue.
-
int
k_delayed_work_cancel
(struct k_delayed_work *work)¶ Cancel a delayed work item.
This routine cancels the submission of delayed work item work. Whether the work item can be successfully cancelled depends on its state.
- Note
Can be called by ISRs.
- Note
When
-EALREADY
is returned the caller cannot distinguish whether the work item handler is still being invoked by the work queue thread or has completed.- Parameters
work
: Address of delayed work item.
- Return Value
0
:Work item countdown cancelled before the item was submitted to its queue; or
Work item was removed from its queue before it was processed.
-EINVAL
:Work item has never been submitted; or
Work item has been successfully cancelled; or
Timeout handler is in the process of submitting the work item to its queue; or
Work queue thread has removed the work item from the queue but has not called its handler.
-EALREADY
:Work queue thread has removed the work item from the queue and cleared its pending flag; or
Work queue thread is invoking the item handler; or
Work item handler has completed.
-
static inline void
k_work_submit
(struct k_work *work)¶ Submit a work item to the system workqueue.
This routine submits work item work to be processed by the system workqueue. If the work item is already pending in the system workqueue or any other workqueue as a result of an earlier submission, this routine has no effect on the work item. If the work item has already been processed, or is currently being processed, its work is considered complete and the work item can be resubmitted.
- Warning
Work items submitted to the system workqueue should avoid using handlers that block or yield since this may prevent the system workqueue from processing other work items in a timely manner.
- Note
Can be called by ISRs.
- Return
N/A
- Parameters
work
: Address of work item.
-
static inline int
k_delayed_work_submit
(struct k_delayed_work *work, k_timeout_t delay)¶ Submit a delayed work item to the system workqueue.
This routine schedules work item work to be processed by the system workqueue after a delay of delay milliseconds. The routine initiates an asynchronous countdown for the work item and then returns to the caller. Only when the countdown completes is the work item actually submitted to the workqueue and becomes pending.
Submitting a previously submitted delayed work item that is still counting down cancels the existing submission and restarts the countdown using the new delay. If the work item is currently pending on the workqueue’s queue because the countdown has completed it is too late to resubmit the item, and resubmission fails without impacting the work item. If the work item has already been processed, or is currently being processed, its work is considered complete and the work item can be resubmitted.
Attempts to submit a work item to a queue after it has been submitted to a different queue will fail with
-EALREADY
until k_delayed_work_cancel() is invoked on the work item to clear its internal state.- Warning
Work items submitted to the system workqueue should avoid using handlers that block or yield since this may prevent the system workqueue from processing other work items in a timely manner.
- Note
Can be called by ISRs.
- Parameters
work
: Address of delayed work item.delay
: Delay before submitting the work item
- Return Value
0
: Work item countdown started.-EINVAL
: Work item is being processed or has completed its work.-EADDRINUSE
: Work item was submitted to a different workqueue.
-
static inline k_ticks_t
k_delayed_work_expires_ticks
(struct k_delayed_work *work)¶ Get time when a delayed work will be scheduled.
This routine computes the system uptime when a delayed work gets executed. If the delayed work is not waiting to be scheduled, it returns current system time.
- Return
Uptime of execution (in ticks).
- Parameters
work
: Delayed work item.
-
static inline k_ticks_t
k_delayed_work_remaining_ticks
(struct k_delayed_work *work)¶ Get time remaining before a delayed work gets scheduled, in system ticks.
This routine computes the time remaining before a delayed work gets executed. If the delayed work is not waiting to be scheduled, it returns zero.
- Return
Remaining time (in ticks).
- Parameters
work
: Delayed work item.
-
static inline int32_t
k_delayed_work_remaining_get
(struct k_delayed_work *work)¶ Get time remaining before a delayed work gets scheduled.
This routine computes the (approximate) time remaining before a delayed work gets executed. If the delayed work is not waiting to be scheduled, it returns zero.
- Return
Remaining time (in milliseconds).
- Parameters
work
: Delayed work item.
-
void
k_work_poll_init
(struct k_work_poll *work, k_work_handler_t handler)¶ Initialize a triggered work item.
This routine initializes a workqueue triggered work item, prior to its first use.
- Return
N/A
- Parameters
work
: Address of triggered work item.handler
: Function to invoke each time work item is processed.
-
int
k_work_poll_submit_to_queue
(struct k_work_q *work_q, struct k_work_poll *work, struct k_poll_event *events, int num_events, k_timeout_t timeout)¶ Submit a triggered work item.
This routine schedules work item work to be processed by workqueue work_q when one of the given events is signaled. The routine initiates internal poller for the work item and then returns to the caller. Only when one of the watched events happen the work item is actually submitted to the workqueue and becomes pending.
Submitting a previously submitted triggered work item that is still waiting for the event cancels the existing submission and reschedules it the using the new event list. Note that this behavior is inherently subject to race conditions with the pre-existing triggered work item and work queue, so care must be taken to synchronize such resubmissions externally.
- Note
Can be called by ISRs.
- Warning
Provided array of events as well as a triggered work item must be placed in persistent memory (valid until work handler execution or work cancellation) and cannot be modified after submission.
- Parameters
work_q
: Address of workqueue.work
: Address of delayed work item.events
: An array of events which trigger the work.num_events
: The number of events in the array.timeout
: Timeout after which the work will be scheduled for execution even if not triggered.
- Return Value
0
: Work item started watching for events.-EINVAL
: Work item is being processed or has completed its work.-EADDRINUSE
: Work item is pending on a different workqueue.
-
static inline int
k_work_poll_submit
(struct k_work_poll *work, struct k_poll_event *events, int num_events, k_timeout_t timeout)¶ Submit a triggered work item to the system workqueue.
This routine schedules work item work to be processed by system workqueue when one of the given events is signaled. The routine initiates internal poller for the work item and then returns to the caller. Only when one of the watched events happen the work item is actually submitted to the workqueue and becomes pending.
Submitting a previously submitted triggered work item that is still waiting for the event cancels the existing submission and reschedules it the using the new event list. Note that this behavior is inherently subject to race conditions with the pre-existing triggered work item and work queue, so care must be taken to synchronize such resubmissions externally.
- Note
Can be called by ISRs.
- Warning
Provided array of events as well as a triggered work item must not be modified until the item has been processed by the workqueue.
- Parameters
work
: Address of delayed work item.events
: An array of events which trigger the work.num_events
: The number of events in the array.timeout
: Timeout after which the work will be scheduled for execution even if not triggered.
- Return Value
0
: Work item started watching for events.-EINVAL
: Work item is being processed or has completed its work.-EADDRINUSE
: Work item is pending on a different workqueue.
-
int
k_work_poll_cancel
(struct k_work_poll *work)¶ Cancel a triggered work item.
This routine cancels the submission of triggered work item work. A triggered work item can only be canceled if no event triggered work submission.
- Note
Can be called by ISRs.
- Parameters
work
: Address of delayed work item.
- Return Value
0
: Work item canceled.-EINVAL
: Work item is being processed or has completed its work.
-
struct
k_thread
¶ - #include <thread.h>
Thread Structure
-