1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/core/include/sched.h
Benjamin Valentin 4d34cee72f core: add comments to symbols used by OpenOCD
OpenOCD makes assumptions about those symbol names / enum entries,
so add a note about it as a comment.
2020-07-27 16:14:42 +02:00

249 lines
7.8 KiB
C

/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup core_sched Scheduler
* @ingroup core
* @brief The RIOT scheduler
* @details
*
* 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.
*
*
* @{
*
* @file
* @brief Scheduler API definition
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef SCHED_H
#define SCHED_H
#include <stddef.h>
#include "kernel_defines.h"
#include "kernel_types.h"
#include "native_sched.h"
#include "clist.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief forward declaration for thread_t, defined in thread.h
*/
typedef struct _thread thread_t;
/**
* @name Thread states supported by RIOT
*
* Keep in sync with OpenOCD src/rtos/riot.c
* @{
*/
typedef enum {
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 */
} thread_status_t;
/** @} */
/**
* @name 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 */
/** @} */
/**
* @def SCHED_PRIO_LEVELS
* @brief The number of thread priority levels
*/
#ifndef SCHED_PRIO_LEVELS
#define SCHED_PRIO_LEVELS 16
#endif
/**
* @brief Triggers the scheduler to schedule the next thread
* @returns 1 if sched_active_thread/sched_active_pid was changed, 0 otherwise.
*/
int sched_run(void);
/**
* @brief Set the status of the specified process
*
* @param[in] process Pointer to the thread control block of the
* targeted process
* @param[in] status The new status of this thread
*/
void sched_set_status(thread_t *process, thread_status_t status);
/**
* @brief Yield if appropriate.
*
* @details 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 @ref sched_context_switch_request is set,
* respectively.
*
* @param[in] other_prio The priority of the target thread.
*/
void sched_switch(uint16_t other_prio);
/**
* @brief Call context switching at thread exit
*/
NORETURN void cpu_switch_context_exit(void);
/**
* Flag indicating whether a context switch is necessary after handling an
* interrupt. Supposed to be set in an ISR.
*/
extern volatile unsigned int sched_context_switch_request;
/**
* Thread table
*/
extern volatile thread_t *sched_threads[KERNEL_PID_LAST + 1];
/**
* Currently active thread
*/
extern volatile thread_t *sched_active_thread;
/**
* Number of running (non-terminated) threads
*/
extern volatile int sched_num_threads;
/**
* Process ID of active thread
*/
extern volatile kernel_pid_t sched_active_pid;
/**
* List of runqueues per priority level
*/
extern clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
/**
* @brief Removes thread from scheduler and set status to #STATUS_STOPPED
*/
NORETURN void sched_task_exit(void);
/**
* @brief 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()'.
*/
void sched_arch_idle(void);
#if IS_USED(MODULE_SCHED_CB) || defined(DOXYGEN)
/**
* @brief Scheduler run callback
*
* @note Both @p active and @p next can be KERNEL_PID_UNDEF, but not at the same
* time.
*
* @param active Pid of the active thread pid
* @param next Pid of the next scheduled thread
*/
typedef void (*sched_callback_t)(kernel_pid_t active, kernel_pid_t next);
/**
* @brief Register a callback that will be called on every scheduler run
*
* @param[in] callback The callback functions that will be called
*/
void sched_register_cb(sched_callback_t callback);
#endif /* MODULE_SCHED_CB */
#ifdef __cplusplus
}
#endif
#endif /* SCHED_H */
/** @} */