Loading...
Searching...
No Matches
Threading

Support for multi-threading. More...

Detailed Description

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:

Flags Description
THREAD_CREATE_SLEEPING the thread will sleep until woken up manually
THREAD_CREATE_WOUT_YIELD the thread might not run immediately after creation
THREAD_CREATE_STACKTEST measures the stack's memory usage

Thread creation

Creating a new thread is internally done in two steps:

  1. the new thread's stack is initialized depending on the platform
  2. 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"
char rcv_thread_stack[THREAD_STACKSIZE_MAIN];
void *rcv_thread(void *arg)
{
(void) arg;
msg_t m;
while (1) {
printf("Got msg from %" PRIkernel_pid "\n", m.sender_pid);
}
return NULL;
}
int main(void)
{
thread_create(rcv_thread_stack, sizeof(rcv_thread_stack),
rcv_thread, NULL, "rcv_thread");
}
int msg_receive(msg_t *m)
Receive a message.
#define PRIkernel_pid
Macro for printing formatter.
Definition sched.h:125
#define THREAD_CREATE_STACKTEST
Write markers into the thread's stack to measure stack usage (for debugging and profiling purposes)
Definition thread.h:237
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...
Definition stdio.h:60
Describes a message object which can be sent between threads.
Definition msg.h:196
kernel_pid_t sender_pid
PID of sending thread.
Definition msg.h:197
#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.

Files

file  thread.h
 Threading API.
 
file  thread_config.h
 Thread configuration defines.
 

Data Structures

struct  _thread
 thread_t holds thread's context data. More...
 

Macros

#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.
 

Typedefs

typedef void *(* thread_task_func_t) (void *arg)
 Prototype for a thread entry function.
 

Functions

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_tthread_get_unchecked (kernel_pid_t pid)
 Retrieve a thread control block by PID.
 
static thread_tthread_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_tthread_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 thread_measure_stack_free (const char *stack)
 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.
 

Optional flags for controlling a threads initial state

#define THREAD_CREATE_SLEEPING   (1)
 Set the new thread to sleeping.
 
#define THREAD_AUTO_FREE   (2)
 Currently not implemented.
 
#define THREAD_CREATE_WOUT_YIELD   (4)
 Do not automatically call thread_yield() after creation: the newly created thread might not run immediately.
 
#define THREAD_CREATE_STACKTEST   (8)
 Write markers into the thread's stack to measure stack usage (for debugging and profiling purposes)
 

Macro Definition Documentation

◆ 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_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   (8)

Write markers into the thread's stack to measure stack usage (for debugging and profiling purposes)

Definition at line 237 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.

Typedef Documentation

◆ 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.

Function Documentation

◆ thread_add_to_list()

void thread_add_to_list ( list_node_t list,
thread_t thread 
)

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]listptr to list root node
[in]threadthread to add

◆ thread_create()

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.

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]stackstart address of the preallocated stack memory
[in]stacksizethe size of the thread's stack in bytes
[in]prioritypriority of the new thread, lower mean higher priority
[in]flagsoptional flags for the creation of the new thread
[in]task_funcpointer to the code that is executed in the new thread
[in]argthe argument to the function
[in]namea 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()

static thread_t * thread_get ( kernel_pid_t  pid)
inlinestatic

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
[in]pidThread to retrieve.
Returns
NULL if the PID is invalid or there is no such thread.

Definition at line 290 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 397 of file thread.h.

◆ thread_get_name()

static const char * thread_get_name ( const thread_t thread)
inlinestatic

Get name of thread.

Parameters
threadthread to work on
Returns
thread name or NULL if not available

Definition at line 614 of file thread.h.

◆ thread_get_priority()

static uint8_t thread_get_priority ( const thread_t thread)
inlinestatic

Get a thread's priority.

Parameters
threadthread to work on
Returns
priority of thread

Definition at line 525 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
threadthread to work on
Returns
current stack pointer

Definition at line 574 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
threadthread to work on
Returns
thread stack size, or 0 if not available

Definition at line 585 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
threadthread to work on
Returns
current stack pointer, or NULL if not available

Definition at line 555 of file thread.h.

◆ thread_get_status()

static thread_status_t thread_get_status ( const thread_t thread)
inlinestatic

Get a thread's status.

Parameters
threadthread to work on
Returns
status of thread

Definition at line 514 of file thread.h.

◆ thread_get_unchecked()

static thread_t * thread_get_unchecked ( kernel_pid_t  pid)
inlinestatic

Retrieve a thread control block by PID.

Precondition
pid is valid
Parameters
[in]pidThread to retrieve.
Returns
NULL if the PID is invalid or there is no such thread.

Definition at line 278 of file thread.h.

◆ thread_getname()

const char * thread_getname ( kernel_pid_t  pid)

Returns the name of a process.

Note
when compiling without DEVELHELP, this always returns NULL!
Parameters
[in]pidthe PID of the thread to get the name from
Returns
the threads name
NULL if pid is unknown

◆ thread_getpid()

static kernel_pid_t thread_getpid ( void  )
inlinestatic

Returns the process ID of the currently running thread.

Returns
obviously you are not a golfer.

Definition at line 383 of file thread.h.

◆ thread_getpid_of()

static kernel_pid_t thread_getpid_of ( const thread_t thread)
inlinestatic

Get PID of thread.

This is a simple getter for thread->pid.

Parameters
threadthread to work on
Returns
thread pid

Definition at line 603 of file thread.h.

◆ thread_getstatus()

thread_status_t thread_getstatus ( kernel_pid_t  pid)

Returns the status of a process.

Parameters
[in]pidthe 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]threadThe thread to check for
Returns
== 0, if thread has no initialized message queue
!= 0, if thread has its message queue initialized

Definition at line 498 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
threadthread to work on
Returns
true if thread is active, false otherwise

Definition at line 536 of file thread.h.

◆ thread_kill_zombie()

int thread_kill_zombie ( kernel_pid_t  pid)

Terminates zombie thread.

Parameters
[in]pidthe 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
[in]stackthe stack you want to measure. Try thread_get_stackstart(thread_get_active())
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_funcFirst function to call within the thread
[in]argArgument to supply to task_func
[in]stack_startStart address of the stack
[in]stack_sizeStack size
Returns
stack pointer

◆ thread_state_to_string()

const char * thread_state_to_string ( thread_status_t  state)

Convert a thread state code to a human readable string.

Parameters
statethread state to convert
Returns
ptr to string representation of thread state (or to "unknown")

◆ thread_wakeup()

int thread_wakeup ( kernel_pid_t  pid)

Wakes up a sleeping thread.

Parameters
[in]pidthe 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()

THREAD_MAYBE_INLINE 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().