diff options
Diffstat (limited to 'include/rtems/score/scheduler.h')
-rw-r--r-- | include/rtems/score/scheduler.h | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/include/rtems/score/scheduler.h b/include/rtems/score/scheduler.h new file mode 100644 index 0000000000..5296644aeb --- /dev/null +++ b/include/rtems/score/scheduler.h @@ -0,0 +1,565 @@ +/** + * @file rtems/score/scheduler.h + * + * @brief Constants and Structures Associated with the Scheduler + * + * This include file contains all the constants and structures associated + * with the scheduler. + */ + +/* + * Copyright (C) 2010 Gedare Bloom. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#ifndef _RTEMS_SCORE_SCHEDULER_H +#define _RTEMS_SCORE_SCHEDULER_H + +#include <rtems/score/priority.h> +#include <rtems/score/thread.h> +#if defined(__RTEMS_HAVE_SYS_CPUSET_H__) && defined(RTEMS_SMP) + #include <sys/cpuset.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct Per_CPU_Control; + +/** + * @defgroup ScoreScheduler Scheduler Handler + * + * @ingroup Score + * + * This handler encapsulates functionality related to managing sets of threads + * that are ready for execution. + */ +/**@{*/ + +typedef struct Scheduler_Control Scheduler_Control; + +typedef struct Scheduler_Node Scheduler_Node; + +#if defined(RTEMS_SMP) + typedef Thread_Control * Scheduler_Void_or_thread; + + #define SCHEDULER_RETURN_VOID_OR_NULL return NULL +#else + typedef void Scheduler_Void_or_thread; + + #define SCHEDULER_RETURN_VOID_OR_NULL return +#endif + +/** + * @brief The scheduler operations. + */ +typedef struct { + /** @see _Scheduler_Handler_initialization() */ + void ( *initialize )( const Scheduler_Control * ); + + /** @see _Scheduler_Schedule() */ + void ( *schedule )( const Scheduler_Control *, Thread_Control *); + + /** @see _Scheduler_Yield() */ + Scheduler_Void_or_thread ( *yield )( + const Scheduler_Control *, + Thread_Control * + ); + + /** @see _Scheduler_Block() */ + void ( *block )( + const Scheduler_Control *, + Thread_Control * + ); + + /** @see _Scheduler_Unblock() */ + Scheduler_Void_or_thread ( *unblock )( + const Scheduler_Control *, + Thread_Control * + ); + + /** @see _Scheduler_Change_priority() */ + Scheduler_Void_or_thread ( *change_priority )( + const Scheduler_Control *, + Thread_Control *, + Priority_Control, + bool + ); + +#if defined(RTEMS_SMP) + /** + * Ask for help operation. + * + * @param[in] scheduler The scheduler of the thread offering help. + * @param[in] offers_help The thread offering help. + * @param[in] needs_help The thread needing help. + * + * @retval needs_help It was not possible to schedule the thread needing + * help, so it is returned to continue the search for help. + * @retval next_needs_help It was possible to schedule the thread needing + * help, but this displaced another thread eligible to ask for help. So + * this thread is returned to start a new search for help. + * @retval NULL It was possible to schedule the thread needing help, and no + * other thread needs help as a result. + * + * @see _Scheduler_Ask_for_help(). + */ + Thread_Control *( *ask_for_help )( + const Scheduler_Control *scheduler, + Thread_Control *offers_help, + Thread_Control *needs_help + ); +#endif + + /** @see _Scheduler_Node_initialize() */ + void ( *node_initialize )( const Scheduler_Control *, Thread_Control * ); + + /** @see _Scheduler_Node_destroy() */ + void ( *node_destroy )( const Scheduler_Control *, Thread_Control * ); + + /** @see _Scheduler_Update_priority() */ + void ( *update_priority )( + const Scheduler_Control *, + Thread_Control *, + Priority_Control + ); + + /** @see _Scheduler_Priority_compare() */ + int ( *priority_compare )( + Priority_Control, + Priority_Control + ); + + /** @see _Scheduler_Release_job() */ + void ( *release_job ) ( + const Scheduler_Control *, + Thread_Control *, + uint32_t + ); + + /** @see _Scheduler_Tick() */ + void ( *tick )( const Scheduler_Control *, Thread_Control * ); + + /** @see _Scheduler_Start_idle() */ + void ( *start_idle )( + const Scheduler_Control *, + Thread_Control *, + struct Per_CPU_Control * + ); + +#if defined(__RTEMS_HAVE_SYS_CPUSET_H__) && defined(RTEMS_SMP) + /** @see _Scheduler_Get_affinity() */ + bool ( *get_affinity )( + const Scheduler_Control *, + Thread_Control *, + size_t, + cpu_set_t * + ); + + /** @see _Scheduler_Set_affinity() */ + bool ( *set_affinity )( + const Scheduler_Control *, + Thread_Control *, + size_t, + const cpu_set_t * + ); +#endif +} Scheduler_Operations; + +/** + * @brief Scheduler context. + * + * The scheduler context of a particular scheduler implementation must place + * this structure at the begin of its context structure. + */ +typedef struct Scheduler_Context { +#if defined(RTEMS_SMP) + /** + * @brief Count of processors owned by this scheduler instance. + */ + uint32_t processor_count; +#endif +} Scheduler_Context; + +/** + * @brief Scheduler control. + */ +struct Scheduler_Control { + /** + * @brief Reference to a statically allocated scheduler context. + */ + Scheduler_Context *context; + + /** + * @brief The scheduler operations. + */ + Scheduler_Operations Operations; + + /** + * @brief The scheduler name. + */ + uint32_t name; +}; + +#if defined(RTEMS_SMP) +/** + * @brief State to indicate potential help for other threads. + * + * @dot + * digraph state { + * y [label="HELP YOURSELF"]; + * ao [label="HELP ACTIVE OWNER"]; + * ar [label="HELP ACTIVE RIVAL"]; + * + * y -> ao [label="obtain"]; + * y -> ar [label="wait for obtain"]; + * ao -> y [label="last release"]; + * ao -> r [label="wait for obtain"]; + * ar -> r [label="timeout"]; + * ar -> ao [label="timeout"]; + * } + * @enddot + */ +typedef enum { + /** + * @brief This scheduler node is solely used by the owner thread. + * + * This thread owns no resources using a helping protocol and thus does not + * take part in the scheduler helping protocol. No help will be provided for + * other thread. + */ + SCHEDULER_HELP_YOURSELF, + + /** + * @brief This scheduler node is owned by a thread actively owning a resource. + * + * This scheduler node can be used to help out threads. + * + * In case this scheduler node changes its state from ready to scheduled and + * the thread executes using another node, then an idle thread will be + * provided as a user of this node to temporarily execute on behalf of the + * owner thread. Thus lower priority threads are denied access to the + * processors of this scheduler instance. + * + * In case a thread actively owning a resource performs a blocking operation, + * then an idle thread will be used also in case this node is in the + * scheduled state. + */ + SCHEDULER_HELP_ACTIVE_OWNER, + + /** + * @brief This scheduler node is owned by a thread actively obtaining a + * resource currently owned by another thread. + * + * This scheduler node can be used to help out threads. + * + * The thread owning this node is ready and will give away its processor in + * case the thread owning the resource asks for help. + */ + SCHEDULER_HELP_ACTIVE_RIVAL, + + /** + * @brief This scheduler node is owned by a thread obtaining a + * resource currently owned by another thread. + * + * This scheduler node can be used to help out threads. + * + * The thread owning this node is blocked. + */ + SCHEDULER_HELP_PASSIVE +} Scheduler_Help_state; +#endif + +/** + * @brief Scheduler node for per-thread data. + */ +struct Scheduler_Node { +#if defined(RTEMS_SMP) + /** + * @brief Chain node for usage in various scheduler data structures. + * + * Strictly this is the wrong place for this field since the data structures + * to manage scheduler nodes belong to the particular scheduler + * implementation. Currently all SMP scheduler implementations use chains. + * The node is here to simplify things, just like the object node in the + * thread control block. It may be replaced with a union to add a red-black + * tree node in the future. + */ + Chain_Node Node; + + /** + * @brief The thread using this node. + */ + Thread_Control *user; + + /** + * @brief The help state of this node. + */ + Scheduler_Help_state help_state; + + /** + * @brief The thread owning this node. + */ + Thread_Control *owner; + + /** + * @brief The idle thread claimed by this node in case the help state is + * SCHEDULER_HELP_ACTIVE_OWNER. + * + * Active owners will lend their own node to an idle thread in case they + * execute currently using another node or in case they perform a blocking + * operation. This is necessary to ensure the priority ceiling protocols + * work across scheduler boundaries. + */ + Thread_Control *idle; + + /** + * @brief The thread accepting help by this node in case the help state is + * not SCHEDULER_HELP_YOURSELF. + */ + Thread_Control *accepts_help; +#endif +}; + +/** + * @brief Registered schedulers. + * + * Application provided via <rtems/confdefs.h>. + * + * @see _Scheduler_Count. + */ +extern const Scheduler_Control _Scheduler_Table[]; + +/** + * @brief Count of registered schedulers. + * + * Application provided via <rtems/confdefs.h> on SMP configurations. + * + * It is very important that this is a compile-time constant on uni-processor + * configurations (in this case RTEMS_SMP is not defined) so that the compiler + * can optimize the some loops away + * + * @see _Scheduler_Table. + */ +#if defined(RTEMS_SMP) + extern const size_t _Scheduler_Count; +#else + #define _Scheduler_Count ( (size_t) 1 ) +#endif + +#if defined(RTEMS_SMP) + /** + * @brief The scheduler assignment default attributes. + */ + #define SCHEDULER_ASSIGN_DEFAULT UINT32_C(0x0) + + /** + * @brief The presence of this processor is optional. + */ + #define SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL SCHEDULER_ASSIGN_DEFAULT + + /** + * @brief The presence of this processor is mandatory. + */ + #define SCHEDULER_ASSIGN_PROCESSOR_MANDATORY UINT32_C(0x1) + + /** + * @brief Scheduler assignment. + */ + typedef struct { + /** + * @brief The scheduler for this processor. + */ + const Scheduler_Control *scheduler; + + /** + * @brief The scheduler assignment attributes. + * + * Use @ref SCHEDULER_ASSIGN_DEFAULT to select default attributes. + * + * The presence of a processor can be + * - @ref SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL, or + * - @ref SCHEDULER_ASSIGN_PROCESSOR_MANDATORY. + */ + uint32_t attributes; + } Scheduler_Assignment; + + /** + * @brief The scheduler assignments. + * + * The length of this array must be equal to the maximum processors. + * + * Application provided via <rtems/confdefs.h>. + * + * @see _Scheduler_Table and rtems_configuration_get_maximum_processors(). + */ + extern const Scheduler_Assignment _Scheduler_Assignments[]; +#endif + +#if defined(RTEMS_SMP) + /** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] offers_help Unused. + * @param[in] needs_help Unused. + * + * @retval NULL Always. + */ + Thread_Control *_Scheduler_default_Ask_for_help( + const Scheduler_Control *scheduler, + Thread_Control *offers_help, + Thread_Control *needs_help + ); + + #define SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP \ + _Scheduler_default_Ask_for_help, +#else + #define SCHEDULER_OPERATION_DEFAULT_ASK_FOR_HELP +#endif + +/** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] the_thread Unused. + */ +void _Scheduler_default_Schedule( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +); + +/** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] the_thread Unused. + */ +void _Scheduler_default_Node_initialize( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +); + +/** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] the_thread Unused. + */ +void _Scheduler_default_Node_destroy( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +); + +/** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] the_thread Unused. + * @param[in] new_priority Unused. + */ +void _Scheduler_default_Update_priority( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Priority_Control new_priority +); + +/** + * @brief Does nothing. + * + * @param[in] scheduler Unused. + * @param[in] the_thread Unused. + * @param[in] deadline Unused. + */ +void _Scheduler_default_Release_job( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + uint32_t deadline +); + +/** + * @brief Performs tick operations depending on the CPU budget algorithm for + * each executing thread. + * + * This routine is invoked as part of processing each clock tick. + * + * @param[in] scheduler The scheduler. + * @param[in] executing An executing thread. + */ +void _Scheduler_default_Tick( + const Scheduler_Control *scheduler, + Thread_Control *executing +); + +/** + * @brief Starts an idle thread. + * + * @param[in] scheduler The scheduler. + * @param[in] the_thread An idle thread. + * @param[in] cpu This parameter is unused. + */ +void _Scheduler_default_Start_idle( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + struct Per_CPU_Control *cpu +); + +#if defined(__RTEMS_HAVE_SYS_CPUSET_H__) && defined(RTEMS_SMP) + /** + * @brief Get affinity for the default scheduler. + * + * @param[in] scheduler The scheduler instance. + * @param[in] thread The associated thread. + * @param[in] cpusetsize The size of the cpuset. + * @param[out] cpuset Affinity set containing all CPUs. + * + * @retval 0 Successfully got cpuset + * @retval -1 The cpusetsize is invalid for the system + */ + bool _Scheduler_default_Get_affinity( + const Scheduler_Control *scheduler, + Thread_Control *thread, + size_t cpusetsize, + cpu_set_t *cpuset + ); + + /** + * @brief Set affinity for the default scheduler. + * + * @param[in] scheduler The scheduler instance. + * @param[in] thread The associated thread. + * @param[in] cpusetsize The size of the cpuset. + * @param[in] cpuset Affinity new affinity set. + * + * @retval 0 Successful + * + * This method always returns successful and does not save + * the cpuset. + */ + bool _Scheduler_default_Set_affinity( + const Scheduler_Control *scheduler, + Thread_Control *thread, + size_t cpusetsize, + const cpu_set_t *cpuset + ); + + #define SCHEDULER_OPERATION_DEFAULT_GET_SET_AFFINITY \ + , _Scheduler_default_Get_affinity \ + , _Scheduler_default_Set_affinity +#else + #define SCHEDULER_OPERATION_DEFAULT_GET_SET_AFFINITY +#endif + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ |