Threading

Support for multi-threading. More...

Detailed Description

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.
 
file  thread_flags.h
 Thread flags.
 

List of thread states

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

Blocked 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 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