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");
}

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.
 

Data Structures

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

Macros

#define CONFIG_THREAD_NAMES
 This global macro enable storage of thread names to help developers. More...
 
#define THREAD_STACKSIZE_DEFAULT
 A reasonable default stack size that will suffice most smaller tasks. More...
 
#define THREAD_STACKSIZE_IDLE
 Size of the idle task's stack in bytes. More...
 
#define THREAD_EXTRA_STACKSIZE_PRINTF
 Size of the task's printf stack in bytes. More...
 
#define THREAD_STACKSIZE_MAIN
 Size of the main task's stack in bytes. More...
 
#define THREAD_STACKSIZE_LARGE   (THREAD_STACKSIZE_MEDIUM * 2)
 Large stack size.
 
#define THREAD_STACKSIZE_MEDIUM   THREAD_STACKSIZE_DEFAULT
 Medium stack size.
 
#define THREAD_STACKSIZE_SMALL   (THREAD_STACKSIZE_MEDIUM / 2)
 Small stack size.
 
#define THREAD_STACKSIZE_TINY   (THREAD_STACKSIZE_MEDIUM / 4)
 Tiny stack size.
 
#define THREAD_STACKSIZE_MINIMUM   (sizeof(thread_t))
 Minimum stack size.
 
#define THREAD_PRIORITY_MIN   (SCHED_PRIO_LEVELS - 1)
 Least priority a thread can have.
 
#define THREAD_PRIORITY_IDLE   (THREAD_PRIORITY_MIN)
 Priority of the idle thread.
 
#define THREAD_PRIORITY_MAIN
 Priority of the main thread. More...
 

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. More...
 
static thread_tthread_get_unchecked (kernel_pid_t pid)
 Retrieve a thread control block by PID. More...
 
static thread_tthread_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_tthread_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...
 

Optional flags for controlling a threads initial state

#define THREAD_CREATE_SLEEPING   (1)
 Set the new thread to sleeping. More...
 
#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. More...
 
#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 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.

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

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 374 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 472 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 581 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_active()->stack_start
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_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()

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

THREAD_PRIORITY_MIN
#define THREAD_PRIORITY_MIN
Least priority a thread can have.
Definition: thread.h:290
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.
THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT
A reasonable default stack size that will suffice most smaller tasks.
Definition: thread.h:211
THREAD_CREATE_STACKTEST
#define THREAD_CREATE_STACKTEST
Write markers into the thread's stack to measure stack usage (for debugging and profiling purposes)
Definition: thread.h:333
PRIkernel_pid
#define PRIkernel_pid
Macro for printing formatter.
Definition: sched.h:120
msg_receive
int msg_receive(msg_t *m)
Receive a message.
THREAD_STACKSIZE_MAIN
#define THREAD_STACKSIZE_MAIN
Size of the main task's stack in bytes.
Definition: thread.h:247
SCHED_PRIO_LEVELS
#define SCHED_PRIO_LEVELS
The number of thread priority levels.
Definition: sched.h:180
msg_t::sender_pid
kernel_pid_t sender_pid
PID of sending thread.
Definition: msg.h:186
msg_t
Describes a message object which can be sent between threads.
Definition: msg.h:185
THREAD_PRIORITY_MAIN
#define THREAD_PRIORITY_MAIN
Priority of the main thread.
Definition: thread.h:303