Scheduler

The RIOT scheduler. More...

Detailed Description

The RIOT scheduler.

RIOT features a tickless, preemptive, priority based scheduler. Context switches can occur either preemptively (i.e. on interrupts), voluntarily, or when a blocking operation (like msg_receive()) is executed. Being tickless means it does not have a timer that fires periodically in order to emulate concurrent execution by switching threads continuously.

Priorities:

Every thread is given a priority on creation. The priority values are "order" or "nice" values, i.e. a higher value means a lower priority.

Example:

Given threads with priorities A=6, B=1, and C=3, B has the highest priority.

A higher priority means that the scheduler will run this thread whenever it becomes runnable instead of a thread with a lower priority. In case of equal priorities, the threads are scheduled in a semi-cooperative fashion. That means that unless an interrupt happens, threads with the same priority will only switch due to voluntary or implicit context switches.

Interrupts:

When an interrupt occurs, e.g. because a timer fired or a network packet was received, the active context is saved and an interrupt service routine (ISR) that handles the interrupt is executed in another context. When the ISR is finished, the sched_context_switch_request flag can be checked. In case it is set, the sched_run() function is called to determine the next active thread. (In the special case that the ISR knows that it can not enable a thread switch, this check can of course be omitted.) If the flag is not set, the original context is being restored and the thread resumes immediately.

Voluntary Context Switches:

There are two function calls that can lead to a voluntary context switch: thread_yield() and thread_sleep(). While the latter disables (think blocks) the thread until it is woken (think unblocked) again via thread_wakeup(), the former only leads to a context switch in case there is another runnable thread with at least the same priority.

Implicit Context Switches:

Some functions that unblock another thread, e.g. msg_send() or mutex_unlock(), can cause a thread switch, if the target had a higher priority.

Modules

 Scheduler for native
 The RIOT scheduler for the native platform.
 

Files

file  sched.h
 Scheduler API definition.
 

Macros

#define MAXTHREADS   32
 The maximum number of threads to be scheduled.
 
#define KERNEL_PID_UNDEF   0
 Canonical identifier for an invalid PID.
 
#define KERNEL_PID_FIRST   (KERNEL_PID_UNDEF + 1)
 The first valid PID (inclusive).
 
#define KERNEL_PID_LAST   (KERNEL_PID_FIRST + MAXTHREADS - 1)
 The last valid PID (inclusive).
 
#define PRIkernel_pid   PRIi16
 Macro for printing formatter.
 
#define SCHED_PRIO_LEVELS   16
 The number of thread priority levels.
 

Typedefs

typedef int16_t kernel_pid_t
 Unique process identifier.
 
typedef struct _thread thread_t
 forward declaration for thread_t, defined in thread.h
 
typedef void(* sched_callback_t) (kernel_pid_t active, kernel_pid_t next)
 Scheduler run callback. More...
 

Functions

static int pid_is_valid (kernel_pid_t pid)
 Determine if the given pid is valid. More...
 
thread_tsched_run (void)
 Triggers the scheduler to schedule the next thread. More...
 
void sched_set_status (thread_t *process, thread_status_t status)
 Set the status of the specified process. More...
 
void sched_switch (uint16_t other_prio)
 Yield if appropriate. More...
 
NORETURN void cpu_switch_context_exit (void)
 Call context switching at thread exit.
 
NORETURN void sched_task_exit (void)
 Removes thread from scheduler and set status to STATUS_STOPPED.
 
void sched_arch_idle (void)
 Set CPU to idle mode (CPU dependent) More...
 
void sched_register_cb (sched_callback_t callback)
 Register a callback that will be called on every scheduler run. More...
 

Variables

volatile unsigned int sched_context_switch_request
 Flag indicating whether a context switch is necessary after handling an interrupt. More...
 
volatile thread_tsched_threads [KERNEL_PID_LAST+1]
 Thread table.
 
volatile int sched_num_threads
 Number of running (non-terminated) threads.
 
clist_node_t sched_runqueues [SCHED_PRIO_LEVELS]
 List of runqueues per priority level.
 

Thread states supported by RIOT

  Keep in sync with OpenOCD src/rtos/riot.c
enum  thread_status_t {
  STATUS_STOPPED, STATUS_ZOMBIE, STATUS_SLEEPING, STATUS_MUTEX_BLOCKED,
  STATUS_RECEIVE_BLOCKED, STATUS_SEND_BLOCKED, STATUS_REPLY_BLOCKED, STATUS_FLAG_BLOCKED_ANY,
  STATUS_FLAG_BLOCKED_ALL, STATUS_MBOX_BLOCKED, STATUS_COND_BLOCKED, STATUS_RUNNING,
  STATUS_PENDING, STATUS_NUMOF
}
 

Helpers to work with thread states

#define STATUS_ON_RUNQUEUE   STATUS_RUNNING
 to check if on run queue: st >= STATUS_ON_RUNQUEUE

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

Typedef Documentation

◆ sched_callback_t

typedef void(* sched_callback_t) (kernel_pid_t active, kernel_pid_t next)

Scheduler run callback.

Note
Both active and next can be KERNEL_PID_UNDEF, but not at the same time.
Parameters
activePid of the active thread pid
nextPid of the next scheduled thread

Definition at line 271 of file sched.h.

Enumeration Type Documentation

◆ thread_status_t

Enumerator
STATUS_STOPPED 

has terminated

STATUS_ZOMBIE 

has terminated & keeps thread's thread_t

STATUS_SLEEPING 

sleeping

STATUS_MUTEX_BLOCKED 

waiting for a locked mutex

STATUS_RECEIVE_BLOCKED 

waiting for a message

STATUS_SEND_BLOCKED 

waiting for message to be delivered

STATUS_REPLY_BLOCKED 

waiting for a message response

STATUS_FLAG_BLOCKED_ANY 

waiting for any flag from flag_mask

STATUS_FLAG_BLOCKED_ALL 

waiting for all flags in flag_mask

STATUS_MBOX_BLOCKED 

waiting for get/put on mbox

STATUS_COND_BLOCKED 

waiting for a condition variable

STATUS_RUNNING 

currently running

STATUS_PENDING 

waiting to be scheduled to run

STATUS_NUMOF 

number of supported thread states

Definition at line 149 of file sched.h.

Function Documentation

◆ pid_is_valid()

static int pid_is_valid ( kernel_pid_t  pid)
inlinestatic

Determine if the given pid is valid.

Parameters
[in]pidThe pid to check
Returns
true if the pid is valid, false otherwise

Definition at line 134 of file sched.h.

◆ sched_arch_idle()

void sched_arch_idle ( void  )

Set CPU to idle mode (CPU dependent)

Only used when there's no idle thread.

This function will be called by the scheduler when there's no runnable thread. It will be called from ISR context, and must allow other ISR handlers to be run. E.g., on Cortex-M, the PendSV priority is temporarily lowered (set to higher value) in order to enable other exceptions to be run.

This function should also invoke setting a low power mode, e.g., by calling 'pm_set_lowest()'.

◆ sched_register_cb()

void sched_register_cb ( sched_callback_t  callback)

Register a callback that will be called on every scheduler run.

Parameters
[in]callbackThe callback functions that will be called

◆ sched_run()

thread_t* sched_run ( void  )

Triggers the scheduler to schedule the next thread.

Returns
The new thread to schedule if sched_active_thread/sched_active_pid was changed,
NULL if the active thread was not changed.

◆ sched_set_status()

void sched_set_status ( thread_t process,
thread_status_t  status 
)

Set the status of the specified process.

Parameters
[in]processPointer to the thread control block of the targeted process
[in]statusThe new status of this thread

◆ sched_switch()

void sched_switch ( uint16_t  other_prio)

Yield if appropriate.

Either yield if other_prio is higher than the current priority, or if the current thread is not on the runqueue.

Depending on whether the current execution is in an ISR (irq_is_in()), thread_yield_higher() is called or sched_context_switch_request is set, respectively.

Parameters
[in]other_prioThe priority of the target thread.

Variable Documentation

◆ sched_context_switch_request

volatile unsigned int sched_context_switch_request

Flag indicating whether a context switch is necessary after handling an interrupt.

Supposed to be set in an ISR.