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");
}
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.
|
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. More...
|
|
static thread_t * | thread_get_unchecked (kernel_pid_t pid) |
| Retrieve a thread control block by PID. More...
|
|
static thread_t * | thread_get (kernel_pid_t pid) |
| Retrieve a thread control block by PID. More...
|
|
thread_status_t | thread_getstatus (kernel_pid_t pid) |
| Returns the status of a process. More...
|
|
void | thread_sleep (void) |
| Puts the current thread into sleep mode. More...
|
|
void | thread_yield (void) |
| Lets current thread yield. More...
|
|
void | thread_yield_higher (void) |
| Lets current thread yield in favor of a higher prioritized thread. More...
|
|
void | thread_zombify (void) |
| Puts the current thread into zombie state. More...
|
|
int | thread_kill_zombie (kernel_pid_t pid) |
| Terminates zombie thread. More...
|
|
int | thread_wakeup (kernel_pid_t pid) |
| Wakes up a sleeping thread. More...
|
|
static kernel_pid_t | thread_getpid (void) |
| Returns the process ID of the currently running thread. More...
|
|
static thread_t * | thread_get_active (void) |
| Returns a pointer to the Thread Control Block of the currently running thread. More...
|
|
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. More...
|
|
void | thread_add_to_list (list_node_t *list, thread_t *thread) |
| Add thread to list, sorted by priority (internal) More...
|
|
const char * | thread_getname (kernel_pid_t pid) |
| Returns the name of a process. More...
|
|
uintptr_t | thread_measure_stack_free (const char *stack) |
| Measures the stack usage of a stack. More...
|
|
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. More...
|
|
◆ 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 143 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 314 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 327 of file thread.h.
◆ THREAD_EXTRA_STACKSIZE_PRINTF
#define THREAD_EXTRA_STACKSIZE_PRINTF |
Size of the task's printf stack in bytes.
- Note
- This value must be defined by the CPU specific implementation, please take a look at
cpu/$CPU/include/cpu_conf
.h
Definition at line 239 of file thread.h.
◆ THREAD_PRIORITY_MAIN
#define THREAD_PRIORITY_MAIN |
Value:
Priority of the main thread.
Definition at line 303 of file thread.h.
◆ THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT |
A reasonable default stack size that will suffice most smaller tasks.
- Note
- This value must be defined by the CPU specific implementation, please take a look at
cpu/$CPU/include/cpu_conf
.h
Definition at line 211 of file thread.h.
◆ THREAD_STACKSIZE_IDLE
#define THREAD_STACKSIZE_IDLE |
Size of the idle task's stack in bytes.
- Note
- This value must be defined by the CPU specific implementation, please take a look at
cpu/$CPU/include/cpu_conf
.h
Definition at line 225 of file thread.h.
◆ THREAD_STACKSIZE_MAIN
#define THREAD_STACKSIZE_MAIN |
Value:
THREAD_EXTRA_STACKSIZE_PRINTF)
Size of the main task's stack in bytes.
Definition at line 247 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 386 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 486 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 374 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 472 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 581 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()
uintptr_t thread_measure_stack_free |
( |
const char * |
stack | ) |
|
Measures the stack usage of a stack.
Only works if the thread was created with the flag THREAD_CREATE_STACKTEST.
- Parameters
-
- Returns
- the amount of unused space of the thread's stack
◆ 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_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()
void thread_yield_higher |
( |
void |
| ) |
|
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().