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 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   (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
 Size of the main task's stack in bytes.
 
#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   (THREAD_PRIORITY_MIN - (SCHED_PRIO_LEVELS/2))
 Priority of the main thread.
 

Functions

kernel_pid_t thread_create (char *stack, int stacksize, char priority, int flags, thread_task_func_t task_func, void *arg, const char *name)
 Creates a new thread. More...
 
volatile thread_tthread_get (kernel_pid_t pid)
 Retreive a thread control block by PID. More...
 
int 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...
 
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...
 
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 (char *stack)
 Measures the stack usage of a stack. More...
 
void thread_print_stack (void)
 Prints human readable, ps-like thread information for debugging purposes.
 

Special meaning thread states

#define STATUS_NOT_FOUND   (-1)
 Describes an illegal thread status.
 

Blocked thread states

#define STATUS_STOPPED   0
 has terminated
 
#define STATUS_SLEEPING   1
 sleeping
 
#define STATUS_MUTEX_BLOCKED   2
 waiting for a locked mutex
 
#define STATUS_RECEIVE_BLOCKED   3
 waiting for a message
 
#define STATUS_SEND_BLOCKED   4
 waiting for message to be delivered
 
#define STATUS_REPLY_BLOCKED   5
 waiting for a message response
 
#define STATUS_FLAG_BLOCKED_ANY   6
 waiting for any flag from flag_mask
 
#define STATUS_FLAG_BLOCKED_ALL   7
 waiting for all flags in flag_mask
 
#define STATUS_MBOX_BLOCKED   8
 waiting for get/put on mbox
 

Queued thread states

#define STATUS_ON_RUNQUEUE   STATUS_RUNNING
 to check if on run queue: st >= STATUS_ON_RUNQUEUE
 
#define STATUS_RUNNING   9
 currently running
 
#define STATUS_PENDING   10
 waiting to be scheduled to run
 

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

◆ THREAD_CREATE_SLEEPING

#define THREAD_CREATE_SLEEPING   (1)

Set the new thread to sleeping.

It must be woken up manually.

Definition at line 290 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 303 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 247 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 218 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 232 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,
char  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()

volatile thread_t* thread_get ( kernel_pid_t  pid)

Retreive 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 retreive.
Returns
NULL if the PID is invalid or there is no such thread.

◆ thread_getname()

const char* thread_getname ( kernel_pid_t  pid)

Returns the name of a process.

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 410 of file thread.h.

◆ thread_getstatus()

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

uintptr_t thread_measure_stack_free ( 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 sched_active_thread->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()