Support for multi-threading.
More...
Support for multi-threading.
Priorities
As RIOT is using a fixed priority scheduling algorithm, threads are scheduled based on their priority. The priority is fixed for every thread and specified during the thread's creation by the priority
parameter.
The lower the priority value, the higher the priority of the thread, with 0 being the highest possible priority.
The lowest possible priority is THREAD_PRIORITY_IDLE - 1.
- Note
- Assigning the same priority to two or more threads is usually not a good idea. A thread in RIOT may run until it yields (thread_yield) or another thread with higher priority is runnable (STATUS_ON_RUNQUEUE) again. Multiple threads with the same priority will therefore be scheduled cooperatively: when one of them is running, all others with the same priority depend on it to yield (or be interrupted by a thread with higher priority). This may make it difficult to determine when which of them gets scheduled and how much CPU time they will get. In most applications, the number of threads in application is significantly smaller than the number of available priorities, so assigning distinct priorities per thread should not be a problem. Only assign the same priority to multiple threads if you know what you are doing!
Thread Behavior
In addition to the priority, flags can be used when creating a thread to alter the thread's behavior after creation. The following flags are available:
Thread creation
Creating a new thread is internally done in two steps:
- the new thread's stack is initialized depending on the platform
- the new thread is added to the scheduler and the scheduler is run (if not indicated otherwise)
- Note
- Creating threads from within an ISR is currently supported, however it is considered to be a bad programming practice and we strongly discourage you from doing so.
Usage
#include "thread.h"
void *rcv_thread(void *arg)
{
(void) arg;
while (1) {
}
return NULL;
}
int main(void)
{
rcv_thread, NULL, "rcv_thread");
}
int msg_receive(msg_t *m)
Receive a message.
#define PRIkernel_pid
Macro for printing formatter.
kernel_pid_t thread_create(char *stack, int stacksize, uint8_t priority, int flags, thread_task_func_t task_func, void *arg, const char *name)
Creates a new thread.
#define printf(...)
A wrapper for the printf() function that passes arguments through unmodified, but fails to compile if...
Describes a message object which can be sent between threads.
kernel_pid_t sender_pid
PID of sending thread.
#define THREAD_STACKSIZE_MAIN
Size of the main task's stack in bytes.
#define THREAD_PRIORITY_MAIN
Priority of the main thread.
Reading from the top down, you can see that first, stack memory for our thread rcv_thread
is preallocated, followed by an implementation of the thread's function. Communication between threads is done using Messaging / IPC. In this case, rcv_thread
will print the process id of each thread that sent a message to rcv_thread
.
After it has been properly defined, rcv_thread
is created with a call to thread_create() in main()
. It is assigned a priority of THREAD_PRIORITY_MAIN - 1
, i.e. a slightly higher priority than the main thread. Since neither the THREAD_CREATE_SLEEPING
nor the THREAD_CREATE_WOUT_YIELD
flag is set, rcv_thread
will be executed immediately.
- Note
- If the messages to the thread are sent using msg_try_send() or from an ISR, activate your thread's message queue by calling msg_init_queue() to prevent messages from being dropped when they can't be handled right away. The same applies if you'd like msg_send() to your thread to be non-blocking. For more details, see the Messaging documentation.
|
#define | THREAD_MAYBE_INLINE |
| Macro definition to inline some of the platform specific implementations.
|
|
#define | CONFIG_THREAD_NAMES |
| This global macro enable storage of thread names to help developers.
|
|
|
kernel_pid_t | thread_create (char *stack, int stacksize, uint8_t priority, int flags, thread_task_func_t task_func, void *arg, const char *name) |
| Creates a new thread.
|
|
static thread_t * | thread_get_unchecked (kernel_pid_t pid) |
| Retrieve a thread control block by PID.
|
|
static thread_t * | thread_get (kernel_pid_t pid) |
| Retrieve a thread control block by PID.
|
|
thread_status_t | thread_getstatus (kernel_pid_t pid) |
| Returns the status of a process.
|
|
void | thread_sleep (void) |
| Puts the current thread into sleep mode.
|
|
void | thread_yield (void) |
| Lets current thread yield.
|
|
THREAD_MAYBE_INLINE void | thread_yield_higher (void) |
| Lets current thread yield in favor of a higher prioritized thread.
|
|
void | thread_zombify (void) |
| Puts the current thread into zombie state.
|
|
int | thread_kill_zombie (kernel_pid_t pid) |
| Terminates zombie thread.
|
|
int | thread_wakeup (kernel_pid_t pid) |
| Wakes up a sleeping thread.
|
|
static kernel_pid_t | thread_getpid (void) |
| Returns the process ID of the currently running thread.
|
|
static thread_t * | thread_get_active (void) |
| Returns a pointer to the Thread Control Block of the currently running thread.
|
|
char * | thread_stack_init (thread_task_func_t task_func, void *arg, void *stack_start, int stack_size) |
| Gets called upon thread creation to set CPU registers.
|
|
void | thread_add_to_list (list_node_t *list, thread_t *thread) |
| Add thread to list, sorted by priority (internal)
|
|
const char * | thread_getname (kernel_pid_t pid) |
| Returns the name of a process.
|
|
uintptr_t | measure_stack_free_internal (const char *stack, size_t size) |
| Measures the stack usage of a stack.
|
|
int | thread_isr_stack_usage (void) |
| Get the number of bytes used on the ISR stack.
|
|
void * | thread_isr_stack_pointer (void) |
| Get the current ISR stack pointer.
|
|
void * | thread_isr_stack_start (void) |
| Get the start of the ISR stack.
|
|
void | thread_stack_print (void) |
| Print the current stack to stdout.
|
|
void | thread_print_stack (void) |
| Prints human readable, ps-like thread information for debugging purposes.
|
|
static int | thread_has_msg_queue (const volatile struct _thread *thread) |
| Checks if a thread has an initialized message queue.
|
|
static thread_status_t | thread_get_status (const thread_t *thread) |
| Get a thread's status.
|
|
static uint8_t | thread_get_priority (const thread_t *thread) |
| Get a thread's priority.
|
|
static bool | thread_is_active (const thread_t *thread) |
| Returns if a thread is active (currently running or waiting to be scheduled)
|
|
const char * | thread_state_to_string (thread_status_t state) |
| Convert a thread state code to a human readable string.
|
|
static void * | thread_get_stackstart (const thread_t *thread) |
| Get start address (lowest) of a thread's stack.
|
|
static void * | thread_get_sp (const thread_t *thread) |
| Get stored Stack Pointer of thread.
|
|
static size_t | thread_get_stacksize (const thread_t *thread) |
| Get size of a thread's stack.
|
|
static kernel_pid_t | thread_getpid_of (const thread_t *thread) |
| Get PID of thread.
|
|
static const char * | thread_get_name (const thread_t *thread) |
| Get name of thread.
|
|
static uintptr_t | thread_measure_stack_free (const thread_t *thread) |
| Measures the stack usage of a stack.
|
|
◆ CONFIG_THREAD_NAMES
#define CONFIG_THREAD_NAMES |
This global macro enable storage of thread names to help developers.
To activate it set environment variable `THREAD_NAMES=1`, or use Kconfig.
It is automatically enabled if `DEVELHELP` is.
Definition at line 157 of file thread.h.
◆ THREAD_AUTO_FREE
#define THREAD_AUTO_FREE (2) |
Currently not implemented.
Definition at line 223 of file thread.h.
◆ THREAD_CREATE_NO_STACKTEST
#define THREAD_CREATE_NO_STACKTEST (8) |
Never write markers into the thread's stack to measure stack usage.
This flag is ignored when DEVELHELP or SCHED_TEST_STACK is not enabled
Definition at line 238 of file thread.h.
◆ THREAD_CREATE_SLEEPING
#define THREAD_CREATE_SLEEPING (1) |
Set the new thread to sleeping.
It must be woken up manually.
Definition at line 218 of file thread.h.
◆ THREAD_CREATE_STACKTEST
#define THREAD_CREATE_STACKTEST (0) |
Legacy flag kept for compatibility.
- Deprecated:
- will be removed after 2025.07 release
This is always enabled with DEVELHELP=1
or SCHED_TEST_STACK
.
Definition at line 247 of file thread.h.
◆ THREAD_CREATE_WOUT_YIELD
#define THREAD_CREATE_WOUT_YIELD (4) |
Do not automatically call thread_yield() after creation: the newly created thread might not run immediately.
Purely for optimization. Any other context switch (i.e. an interrupt) can still start the thread at any time!
Definition at line 231 of file thread.h.
◆ THREAD_MAYBE_INLINE
#define THREAD_MAYBE_INLINE |
Macro definition to inline some of the platform specific implementations.
Should be enabled when advantageous by CPU's in their thread_arch.h header
Definition at line 147 of file thread.h.
◆ thread_task_func_t
typedef void *(* thread_task_func_t) (void *arg) |
Prototype for a thread entry function.
Definition at line 163 of file thread.h.
◆ thread_add_to_list()
Add thread to list, sorted by priority (internal)
This will add thread
to list
sorted by the thread priority. It reuses the thread's rq_entry field. Used internally by msg and mutex implementations.
- Note
- Only use for threads not on any runqueue and with interrupts disabled.
- Parameters
-
[in] | list | ptr to list root node |
[in] | thread | thread to add |
◆ thread_create()
Creates a new thread.
For an in-depth discussion of thread priorities, behavior and and flags, see Threading.
- Note
- Avoid assigning the same priority to two or more threads.
-
Creating threads from within an ISR is currently supported, however it is considered to be a bad programming practice and we strongly discourage you from doing so.
- Parameters
-
[out] | stack | start address of the preallocated stack memory |
[in] | stacksize | the size of the thread's stack in bytes |
[in] | priority | priority of the new thread, lower mean higher priority |
[in] | flags | optional flags for the creation of the new thread |
[in] | task_func | pointer to the code that is executed in the new thread |
[in] | arg | the argument to the function |
[in] | name | a human readable descriptor for the thread |
- Returns
- PID of newly created task on success
-
-EINVAL, if
priority
is greater than or equal to SCHED_PRIO_LEVELS
-
-EOVERFLOW, if there are too many threads running already
◆ thread_get()
Retrieve a thread control block by PID.
This is a bound-checked variant of accessing sched_threads[pid]
directly. If you know that the PID is valid, then don't use this function.
- Parameters
-
- Returns
NULL
if the PID is invalid or there is no such thread.
Definition at line 300 of file thread.h.
◆ thread_get_active()
static thread_t * thread_get_active |
( |
void |
| ) |
|
|
inlinestatic |
Returns a pointer to the Thread Control Block of the currently running thread.
- Returns
- Pointer to the TCB of the currently running thread, or
NULL
if no thread is running
Definition at line 407 of file thread.h.
◆ thread_get_name()
static const char * thread_get_name |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Get name of thread.
- Parameters
-
- Returns
- thread name or NULL if not available
Definition at line 630 of file thread.h.
◆ thread_get_priority()
static uint8_t thread_get_priority |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Get a thread's priority.
- Parameters
-
- Returns
- priority of thread
Definition at line 541 of file thread.h.
◆ thread_get_sp()
static void * thread_get_sp |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Get stored Stack Pointer of thread.
Only provides meaningful value if the thread is not currently running!.
- Parameters
-
- Returns
- current stack pointer
Definition at line 590 of file thread.h.
◆ thread_get_stacksize()
static size_t thread_get_stacksize |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Get size of a thread's stack.
- Parameters
-
- Returns
- thread stack size, or 0 if not available
Definition at line 601 of file thread.h.
◆ thread_get_stackstart()
static void * thread_get_stackstart |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Get start address (lowest) of a thread's stack.
- Parameters
-
- Returns
- current stack pointer, or NULL if not available
Definition at line 571 of file thread.h.
◆ thread_get_status()
Get a thread's status.
- Parameters
-
- Returns
- status of thread
Definition at line 530 of file thread.h.
◆ thread_get_unchecked()
Retrieve a thread control block by PID.
- Precondition
pid
is valid
- Parameters
-
- Returns
NULL
if the PID is invalid or there is no such thread.
Definition at line 288 of file thread.h.
◆ thread_getname()
Returns the name of a process.
- Note
- when compiling without DEVELHELP, this always returns NULL!
- Parameters
-
[in] | pid | the PID of the thread to get the name from |
- Returns
- the threads name
-
NULL
if pid is unknown
◆ thread_getpid()
Returns the process ID of the currently running thread.
- Returns
- obviously you are not a golfer.
Definition at line 393 of file thread.h.
◆ thread_getpid_of()
Get PID of thread.
This is a simple getter for thread->pid.
- Parameters
-
- Returns
- thread pid
Definition at line 619 of file thread.h.
◆ thread_getstatus()
Returns the status of a process.
- Parameters
-
[in] | pid | the PID of the thread to get the status from |
- Returns
- status of the thread
-
STATUS_NOT_FOUND
if pid is unknown
◆ thread_has_msg_queue()
static int thread_has_msg_queue |
( |
const volatile struct _thread * |
thread | ) |
|
|
inlinestatic |
Checks if a thread has an initialized message queue.
- See also
- msg_init_queue()
- Parameters
-
[in] | thread | The thread to check for |
- Returns
== 0
, if thread
has no initialized message queue
-
!= 0
, if thread
has its message queue initialized
Definition at line 514 of file thread.h.
◆ thread_is_active()
static bool thread_is_active |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Returns if a thread is active (currently running or waiting to be scheduled)
- Parameters
-
- Returns
- true if thread is active, false otherwise
Definition at line 552 of file thread.h.
◆ thread_kill_zombie()
Terminates zombie thread.
- Parameters
-
[in] | pid | the PID of the thread to terminate |
- Returns
1
on success
-
STATUS_NOT_FOUND
if pid is unknown or not a zombie
◆ thread_measure_stack_free()
static uintptr_t thread_measure_stack_free |
( |
const thread_t * |
thread | ) |
|
|
inlinestatic |
Measures the stack usage of a stack.
- Precondition
- Does not work if the thread was created with the flag
THREAD_CREATE_NO_STACKTEST
.
- Parameters
-
[in] | thread | The thread to measure the stack of |
- Returns
- the amount of unused space of the thread's stack
Definition at line 650 of file thread.h.
◆ thread_sleep()
void thread_sleep |
( |
void |
| ) |
|
Puts the current thread into sleep mode.
Has to be woken up externally.
◆ thread_stack_init()
char * thread_stack_init |
( |
thread_task_func_t |
task_func, |
|
|
void * |
arg, |
|
|
void * |
stack_start, |
|
|
int |
stack_size |
|
) |
| |
Gets called upon thread creation to set CPU registers.
- Parameters
-
[in] | task_func | First function to call within the thread |
[in] | arg | Argument to supply to task_func |
[in] | stack_start | Start address of the stack |
[in] | stack_size | Stack size |
- Returns
- stack pointer
◆ thread_state_to_string()
Convert a thread state code to a human readable string.
- Parameters
-
state | thread state to convert |
- Returns
- ptr to string representation of thread state (or to "unknown")
◆ thread_wakeup()
Wakes up a sleeping thread.
- Parameters
-
[in] | pid | the PID of the thread to be woken up |
- Returns
1
on success
-
STATUS_NOT_FOUND
if pid is unknown or not sleeping
◆ thread_yield()
void thread_yield |
( |
void |
| ) |
|
Lets current thread yield.
The current thread will resume operation immediately, if there is no other ready thread with the same or a higher priority.
Differently from thread_yield_higher() the current thread will be put to the end of the thread's in its priority class.
- See also
- thread_yield_higher()
◆ thread_yield_higher()
Lets current thread yield in favor of a higher prioritized thread.
The current thread will resume operation immediately, if there is no other ready thread with a higher priority.
Differently from thread_yield() the current thread will be scheduled next in its own priority class, i.e. it stays the first thread in its priority class.
- See also
- thread_yield()
◆ thread_zombify()
void thread_zombify |
( |
void |
| ) |
|
Puts the current thread into zombie state.
Does nothing when in ISR. A thread in zombie state will never be scheduled again, but its scheduler entry and stack will be kept. A zombie state thread is supposed to be cleaned up by thread_kill_zombie().