diff options
40 files changed, 553 insertions, 230 deletions
diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h index ad432ed82c..1c97d153ba 100644 --- a/cpukit/sapi/include/confdefs.h +++ b/cpukit/sapi/include/confdefs.h @@ -2474,18 +2474,24 @@ const rtems_libio_helper rtems_fs_init_helper = void *extensions[ CONFIGURE_MAXIMUM_USER_EXTENSIONS + 1 ]; #endif union { + Scheduler_Node Base; #ifdef CONFIGURE_SCHEDULER_CBS - Scheduler_CBS_Per_thread CBS; + Scheduler_CBS_Node CBS; #endif #ifdef CONFIGURE_SCHEDULER_EDF - Scheduler_EDF_Per_thread EDF; + Scheduler_EDF_Node EDF; #endif - #if defined(CONFIGURE_SCHEDULER_PRIORITY) \ - || defined(CONFIGURE_SCHEDULER_PRIORITY_SMP) - Scheduler_priority_Per_thread Priority; + #ifdef CONFIGURE_SCHEDULER_PRIORITY + Scheduler_priority_Node Priority; + #endif + #ifdef CONFIGURE_SCHEDULER_SIMPLE_SMP + Scheduler_SMP_Node Simple_SMP; + #endif + #ifdef CONFIGURE_SCHEDULER_PRIORITY_SMP + Scheduler_priority_SMP_Node Priority_SMP; #endif #ifdef CONFIGURE_SCHEDULER_PRIORITY_AFFINITY_SMP - Scheduler_priority_affinity_SMP_Per_thread Priority_affinity; + Scheduler_priority_affinity_SMP_Node Priority_affinity_SMP; #endif #ifdef CONFIGURE_SCHEDULER_USER_PER_THREAD CONFIGURE_SCHEDULER_USER_PER_THREAD User; @@ -2511,7 +2517,7 @@ const rtems_libio_helper rtems_fs_init_helper = const Thread_Control_add_on _Thread_Control_add_ons[] = { { - offsetof( Configuration_Thread_control, Control.scheduler_info ), + offsetof( Configuration_Thread_control, Control.scheduler_node ), offsetof( Configuration_Thread_control, Scheduler ) }, { offsetof( diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index ae925507d1..8fb11d7bdf 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -52,6 +52,7 @@ include_rtems_score_HEADERS += include/rtems/score/rbtreeimpl.h include_rtems_score_HEADERS += include/rtems/score/scheduler.h include_rtems_score_HEADERS += include/rtems/score/schedulerimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulercbs.h +include_rtems_score_HEADERS += include/rtems/score/schedulercbsimpl.h include_rtems_score_HEADERS += include/rtems/score/scheduleredf.h include_rtems_score_HEADERS += include/rtems/score/scheduleredfimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulerpriority.h @@ -126,6 +127,7 @@ endif if HAS_SMP libscore_a_SOURCES += src/profilingsmplock.c +libscore_a_SOURCES += src/schedulersmpvalidstatechanges.c libscore_a_SOURCES += src/schedulerpriorityaffinitysmp.c libscore_a_SOURCES += src/schedulerprioritysmp.c libscore_a_SOURCES += src/schedulersimplesmp.c diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index 768576fef9..7f0b43ae52 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -42,6 +42,8 @@ extern "C" { typedef struct Scheduler_Control Scheduler_Control; +typedef struct Scheduler_Node Scheduler_Node; + /** * @brief The scheduler operations. */ @@ -157,6 +159,13 @@ struct Scheduler_Control { }; /** + * @brief Scheduler node for per-thread data. + */ +struct Scheduler_Node { + /* No fields yet */ +}; + +/** * @brief Registered schedulers. * * Application provided via <rtems/confdefs.h>. diff --git a/cpukit/score/include/rtems/score/schedulercbs.h b/cpukit/score/include/rtems/score/schedulercbs.h index e546c8d1e3..6cfdfbe959 100644 --- a/cpukit/score/include/rtems/score/schedulercbs.h +++ b/cpukit/score/include/rtems/score/schedulercbs.h @@ -129,10 +129,10 @@ typedef struct { */ typedef struct { /** EDF scheduler specific data of a task. */ - Scheduler_EDF_Per_thread edf_per_thread; + Scheduler_EDF_Node Base; /** CBS server specific data of a task. */ Scheduler_CBS_Server *cbs_server; -} Scheduler_CBS_Per_thread; +} Scheduler_CBS_Node; /** diff --git a/cpukit/score/include/rtems/score/schedulercbsimpl.h b/cpukit/score/include/rtems/score/schedulercbsimpl.h new file mode 100644 index 0000000000..f40de0712e --- /dev/null +++ b/cpukit/score/include/rtems/score/schedulercbsimpl.h @@ -0,0 +1,52 @@ +/** + * @file + * + * @brief CBS Scheduler Implementation + * + * @ingroup ScoreSchedulerCBS + */ + +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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_SCHEDULERCBSIMPL_H +#define _RTEMS_SCORE_SCHEDULERCBSIMPL_H + +#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulerimpl.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @addtogroup ScoreSchedulerCBS + * + * @{ + */ + +RTEMS_INLINE_ROUTINE Scheduler_CBS_Node *_Scheduler_CBS_Node_get( + Thread_Control *the_thread +) +{ + return (Scheduler_CBS_Node *) _Scheduler_Node_get( the_thread ); +} + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _RTEMS_SCORE_SCHEDULERCBSIMPL_H */ diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h index fabce7e288..95be94c802 100644 --- a/cpukit/score/include/rtems/score/scheduleredf.h +++ b/cpukit/score/include/rtems/score/scheduleredf.h @@ -91,10 +91,15 @@ typedef enum { } Scheduler_EDF_Queue_state; /** - * This structure handles EDF specific data of a thread. + * @brief Scheduler node specialization for EDF schedulers. */ typedef struct { /** + * @brief Basic scheduler node. + */ + Scheduler_Node Base; + + /** * Pointer to corresponding Thread Control Block. */ Thread_Control *thread; @@ -106,7 +111,7 @@ typedef struct { * State of the thread with respect to ready queue. */ Scheduler_EDF_Queue_state queue_state; -} Scheduler_EDF_Per_thread; +} Scheduler_EDF_Node; /** * @brief Initialize EDF scheduler. diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h index d4b197e442..708557f78e 100644 --- a/cpukit/score/include/rtems/score/scheduleredfimpl.h +++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h @@ -37,6 +37,13 @@ RTEMS_INLINE_ROUTINE Scheduler_EDF_Context * return (Scheduler_EDF_Context *) scheduler->context; } +RTEMS_INLINE_ROUTINE Scheduler_EDF_Node *_Scheduler_EDF_Node_get( + Thread_Control *the_thread +) +{ + return (Scheduler_EDF_Node *) _Scheduler_Node_get( the_thread ); +} + RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body( const Scheduler_Control *scheduler, Thread_Control *the_thread, @@ -46,9 +53,9 @@ RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body( Scheduler_EDF_Context *context = _Scheduler_EDF_Get_context( scheduler ); RBTree_Node *first = _RBTree_First( &context->Ready, RBT_LEFT ); - Scheduler_EDF_Per_thread *sched_info = - _RBTree_Container_of(first, Scheduler_EDF_Per_thread, Node); - Thread_Control *heir = (Thread_Control *) sched_info->thread; + Scheduler_EDF_Node *node = + _RBTree_Container_of(first, Scheduler_EDF_Node, Node); + Thread_Control *heir = node->thread; ( void ) the_thread; diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 42e57303b8..c972ef57bd 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -623,6 +623,13 @@ RTEMS_INLINE_ROUTINE uint32_t _Scheduler_Get_index( return (uint32_t) (scheduler - &_Scheduler_Table[ 0 ]); } +RTEMS_INLINE_ROUTINE Scheduler_Node *_Scheduler_Node_get( + Thread_Control *the_thread +) +{ + return the_thread->scheduler_node; +} + /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h index 4393b7ddb5..134dcd715b 100644 --- a/cpukit/score/include/rtems/score/schedulerpriority.h +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -83,7 +83,7 @@ typedef struct { } Scheduler_priority_Context; /** - * Per-thread data related to the _Scheduler_PRIORITY scheduling policy. + * @brief Data for ready queue operations. */ typedef struct { /** This field points to the Ready FIFO for this thread's priority. */ @@ -91,7 +91,22 @@ typedef struct { /** This field contains precalculated priority map indices. */ Priority_bit_map_Information Priority_map; -} Scheduler_priority_Per_thread; +} Scheduler_priority_Ready_queue; + +/** + * @brief Scheduler node specialization for Deterministic Priority schedulers. + */ +typedef struct { + /** + * @brief Basic scheduler node. + */ + Scheduler_Node Base; + + /** + * @brief The associated ready queue of this node. + */ + Scheduler_priority_Ready_queue Ready_queue; +} Scheduler_priority_Node; /** * @brief Initializes the priority scheduler. diff --git a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h index c327fccb6e..e86fd35c6f 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h @@ -118,25 +118,20 @@ bool _Scheduler_priority_affinity_SMP_Set_affinity( ); /** - * This structure handles affinity specific data of a thread. - * - * @note The attribute priority_sched_info must remain - * the first element in the structure so that the - * Scheduler_priority_XXX methods will continue to - * function. + * @brief Scheduler node specialization for Deterministic Priority Affinity SMP + * schedulers. */ typedef struct { - /** - * Data for the Priority Scheduler. + * @brief SMP priority scheduler node. */ - Scheduler_priority_Per_thread Priority_sched_info; + Scheduler_priority_SMP_Node Base; /** * Structure containing affinity set data and size */ CPU_set_Control Affinity; -} Scheduler_priority_affinity_SMP_Per_thread; +} Scheduler_priority_affinity_SMP_Node; /** @} */ diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h index fde06872ca..3fb1e5b622 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h @@ -41,6 +41,13 @@ RTEMS_INLINE_ROUTINE Scheduler_priority_Context * return (Scheduler_priority_Context *) scheduler->context; } +RTEMS_INLINE_ROUTINE Scheduler_priority_Node *_Scheduler_priority_Node_get( + Thread_Control *the_thread +) +{ + return (Scheduler_priority_Node *) _Scheduler_Node_get( the_thread ); +} + /** * @brief Ready queue initialization. * @@ -57,77 +64,72 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_initialize( _Chain_Initialize_empty( &ready_queues[index] ); } -RTEMS_INLINE_ROUTINE Scheduler_priority_Per_thread * +RTEMS_INLINE_ROUTINE Scheduler_priority_Node * _Scheduler_priority_Get_scheduler_info( Thread_Control *thread ) { - return ( Scheduler_priority_Per_thread * ) thread->scheduler_info; + return ( Scheduler_priority_Node * ) thread->scheduler_node; } /** - * @brief Put a thread to the ready queue. + * @brief Enqueues a thread on the specified ready queue. * - * This routine puts @a the_thread on to the priority-based ready queue. + * The thread is placed as the last element of its priority group. * * @param[in] the_thread The thread to enqueue. + * @param[in] ready_queue The ready queue. * @param[in] bit_map The priority bit map of the scheduler instance. */ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue( - Thread_Control *the_thread, - Priority_bit_map_Control *bit_map + Thread_Control *the_thread, + Scheduler_priority_Ready_queue *ready_queue, + Priority_bit_map_Control *bit_map ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( the_thread ); - Chain_Control *ready_chain = sched_info_of_thread->ready_chain; + Chain_Control *ready_chain = ready_queue->ready_chain; _Chain_Append_unprotected( ready_chain, &the_thread->Object.Node ); - _Priority_bit_map_Add( bit_map, &sched_info_of_thread->Priority_map ); + _Priority_bit_map_Add( bit_map, &ready_queue->Priority_map ); } /** - * @brief Put a thread to the head of the ready queue. + * @brief Enqueues a thread on the specified ready queue as first. * - * This routine puts @a the_thread to the head of the ready queue. - * For priority-based ready queues, the thread will be the first thread - * at its priority level. + * The thread is placed as the first element of its priority group. * - * @param[in] the_thread The thread to enqueue. + * @param[in] the_thread The thread to enqueue as first. + * @param[in] ready_queue The ready queue. * @param[in] bit_map The priority bit map of the scheduler instance. */ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_enqueue_first( - Thread_Control *the_thread, - Priority_bit_map_Control *bit_map + Thread_Control *the_thread, + Scheduler_priority_Ready_queue *ready_queue, + Priority_bit_map_Control *bit_map ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( the_thread ); - Chain_Control *ready_chain = sched_info_of_thread->ready_chain; + Chain_Control *ready_chain = ready_queue->ready_chain; _Chain_Prepend_unprotected( ready_chain, &the_thread->Object.Node ); - _Priority_bit_map_Add( bit_map, &sched_info_of_thread->Priority_map ); + _Priority_bit_map_Add( bit_map, &ready_queue->Priority_map ); } /** - * @brief Remove a specific thread from the ready queue. - * - * This routine removes a specific thread from the specified - * priority-based ready queue. + * @brief Extracts a thread from the specified ready queue. * * @param[in] the_thread The thread to extract. + * @param[in] ready_queue The ready queue. * @param[in] bit_map The priority bit map of the scheduler instance. */ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_extract( - Thread_Control *the_thread, - Priority_bit_map_Control *bit_map + Thread_Control *the_thread, + Scheduler_priority_Ready_queue *ready_queue, + Priority_bit_map_Control *bit_map ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( the_thread ); - Chain_Control *ready_chain = sched_info_of_thread->ready_chain; + Chain_Control *ready_chain = ready_queue->ready_chain; if ( _Chain_Has_only_one_node( ready_chain ) ) { _Chain_Initialize_empty( ready_chain ); - _Priority_bit_map_Remove( bit_map, &sched_info_of_thread->Priority_map ); + _Priority_bit_map_Remove( bit_map, &ready_queue->Priority_map ); } else { _Chain_Extract_unprotected( &the_thread->Object.Node ); } @@ -140,8 +142,13 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Extract_body( { Scheduler_priority_Context *context = _Scheduler_priority_Get_context( scheduler ); + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); - _Scheduler_priority_Ready_queue_extract( the_thread, &context->Bit_map ); + _Scheduler_priority_Ready_queue_extract( + the_thread, + &node->Ready_queue, + &context->Bit_map + ); } /** @@ -165,20 +172,20 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_priority_Ready_queue_first( } /** - * @brief Requeue a thread on the ready queue. + * @brief Requeues a thread on the specified ready queue. * * This routine is invoked when a thread changes priority and should be * moved to a different position on the ready queue. * - * @param[in] the_thread is a pointer to the thread + * @param[in] the_thread The thread to requeue. + * @param[in] ready_queue The ready queue. */ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_requeue( - Thread_Control *the_thread + Thread_Control *the_thread, + Scheduler_priority_Ready_queue *ready_queue ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( the_thread ); - Chain_Control *ready_chain = sched_info_of_thread->ready_chain; + Chain_Control *ready_chain = ready_queue->ready_chain; if ( !_Chain_Has_only_one_node( ready_chain ) ) { _Chain_Extract_unprotected( &the_thread->Object.Node ); @@ -210,22 +217,29 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body( _Scheduler_Update_heir( heir, force_dispatch ); } -RTEMS_INLINE_ROUTINE void _Scheduler_priority_Update_body( - Thread_Control *thread, - Priority_bit_map_Control *bit_map, - Chain_Control *ready_queues +/** + * @brief Updates the specified ready queue data according to the current + * priority of the thread. + * + * @param[in] the_thread The thread. + * @param[in] ready_queue The ready queue. + * @param[in] bit_map The priority bit map of the scheduler instance. + * @param[in] ready_queues The ready queues of the scheduler instance. + */ +RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_update( + Thread_Control *the_thread, + Scheduler_priority_Ready_queue *ready_queue, + Priority_bit_map_Control *bit_map, + Chain_Control *ready_queues ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( thread ); - - sched_info_of_thread->ready_chain = - &ready_queues[ thread->current_priority ]; + Priority_Control priority = the_thread->current_priority; + ready_queue->ready_chain = &ready_queues[ priority ]; _Priority_bit_map_Initialize_information( bit_map, - &sched_info_of_thread->Priority_map, - thread->current_priority + &ready_queue->Priority_map, + priority ); } diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h index 66de9645bd..3e7d22f81d 100644 --- a/cpukit/score/include/rtems/score/schedulerprioritysmp.h +++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h @@ -47,13 +47,33 @@ extern "C" { * @{ */ +/** + * @brief Scheduler context specialization for Deterministic Priority SMP + * schedulers. + */ typedef struct { Scheduler_SMP_Context Base; Priority_bit_map_Control Bit_map; - Chain_Control Ready[ 0 ]; + Chain_Control Ready[ RTEMS_ZERO_LENGTH_ARRAY ]; } Scheduler_priority_SMP_Context; /** + * @brief Scheduler node specialization for Deterministic Priority SMP + * schedulers. + */ +typedef struct { + /** + * @brief SMP scheduler node. + */ + Scheduler_SMP_Node Base; + + /** + * @brief The associated ready queue of this node. + */ + Scheduler_priority_Ready_queue Ready_queue; +} Scheduler_priority_SMP_Node; + +/** * @brief Entry points for the Priority SMP Scheduler. */ #define SCHEDULER_PRIORITY_SMP_ENTRY_POINTS \ @@ -63,7 +83,7 @@ typedef struct { _Scheduler_priority_SMP_Yield, \ _Scheduler_priority_SMP_Block, \ _Scheduler_priority_SMP_Enqueue_fifo, \ - _Scheduler_default_Allocate, \ + _Scheduler_priority_SMP_Allocate, \ _Scheduler_default_Free, \ _Scheduler_priority_SMP_Update, \ _Scheduler_priority_SMP_Enqueue_fifo, \ @@ -79,6 +99,11 @@ typedef struct { void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler ); +bool _Scheduler_priority_SMP_Allocate( + const Scheduler_Control *scheduler, + Thread_Control *thread +); + void _Scheduler_priority_SMP_Schedule( const Scheduler_Control *scheduler, Thread_Control *thread diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h index 880115faaf..268d88fe8a 100644 --- a/cpukit/score/include/rtems/score/schedulersimplesmp.h +++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h @@ -64,7 +64,7 @@ typedef struct { _Scheduler_simple_smp_Yield, \ _Scheduler_simple_smp_Block, \ _Scheduler_simple_smp_Enqueue_priority_fifo, \ - _Scheduler_default_Allocate, \ + _Scheduler_simple_smp_Allocate, \ _Scheduler_default_Free, \ _Scheduler_default_Update, \ _Scheduler_simple_smp_Enqueue_priority_fifo, \ @@ -80,6 +80,11 @@ typedef struct { void _Scheduler_simple_smp_Initialize( const Scheduler_Control *scheduler ); +bool _Scheduler_simple_smp_Allocate( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +); + void _Scheduler_simple_smp_Block( const Scheduler_Control *scheduler, Thread_Control *thread diff --git a/cpukit/score/include/rtems/score/schedulersmp.h b/cpukit/score/include/rtems/score/schedulersmp.h index 778a1fb832..ee1b087ff8 100644 --- a/cpukit/score/include/rtems/score/schedulersmp.h +++ b/cpukit/score/include/rtems/score/schedulersmp.h @@ -38,15 +38,81 @@ extern "C" { * @{ */ +/** + * @brief Scheduler context specialization for SMP schedulers. + */ typedef struct { /** * @brief Basic scheduler context. */ Scheduler_Context Base; + /** + * @brief The chain of scheduled nodes. + */ Chain_Control Scheduled; } Scheduler_SMP_Context; +/** + * @brief SMP scheduler node states. + */ +typedef enum { + /** + * @brief This scheduler node is blocked. + * + * A scheduler node is blocked if the corresponding thread is not ready. + */ + SCHEDULER_SMP_NODE_BLOCKED, + + /** + * @brief The scheduler node is scheduled. + * + * A scheduler node is scheduled if the corresponding thread is ready and the + * scheduler allocated a processor for it. A scheduled node is assigned to + * exactly one processor. The sum of scheduled and in the air nodes equals + * the processor count owned by a scheduler instance. + */ + SCHEDULER_SMP_NODE_SCHEDULED, + + /** + * @brief This scheduler node is ready. + * + * A scheduler node is ready if the corresponding thread is ready and the + * scheduler did not allocate a processor for it. + */ + SCHEDULER_SMP_NODE_READY, + + /** + * @brief This scheduler node is in the air. + * + * A scheduled node is in the air if it has an allocated processor and the + * corresponding thread is in a transient state. Such a node is not an + * element of the set of scheduled nodes. The extract operation on a + * scheduled node will produce a scheduler node in the air (see also + * _Thread_Set_transient()). The next enqueue or schedule operation will + * decide what to do based on this state indication. It can either place the + * scheduler node back on the set of scheduled nodes and the thread can keep + * its allocated processor, or it can take the processor away from the thread + * and give the processor to another thread of higher priority. + */ + SCHEDULER_SMP_NODE_IN_THE_AIR +} Scheduler_SMP_Node_state; + +/** + * @brief Scheduler node specialization for SMP schedulers. + */ +typedef struct { + /** + * @brief Basic scheduler node. + */ + Scheduler_Node Base; + + /** + * @brief The state of this node. + */ + Scheduler_SMP_Node_state state; +} Scheduler_SMP_Node; + /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h index 69222c28f8..3bbd4bb0a7 100644 --- a/cpukit/score/include/rtems/score/schedulersmpimpl.h +++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h @@ -64,6 +64,34 @@ static inline void _Scheduler_SMP_Initialize( _Chain_Initialize_empty( &self->Scheduled ); } +static inline Scheduler_SMP_Node *_Scheduler_SMP_Node_get( + Thread_Control *thread +) +{ + return (Scheduler_SMP_Node *) _Scheduler_Node_get( thread ); +} + +static inline void _Scheduler_SMP_Node_initialize( + Scheduler_SMP_Node *node +) +{ + node->state = SCHEDULER_SMP_NODE_BLOCKED; +} + +extern const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ]; + +static inline void _Scheduler_SMP_Node_change_state( + Scheduler_SMP_Node *node, + Scheduler_SMP_Node_state new_state +) +{ + _Assert( + _Scheduler_SMP_Node_valid_state_changes[ node->state ][ new_state ] + ); + + node->state = new_state; +} + static inline bool _Scheduler_SMP_Is_processor_owned_by_us( const Scheduler_SMP_Context *self, const Per_CPU_Control *cpu @@ -106,13 +134,16 @@ static inline void _Scheduler_SMP_Allocate_processor( Thread_Control *victim ) { + Scheduler_SMP_Node *scheduled_node = _Scheduler_SMP_Node_get( scheduled ); Per_CPU_Control *cpu_of_scheduled = _Thread_Get_CPU( scheduled ); Per_CPU_Control *cpu_of_victim = _Thread_Get_CPU( victim ); Per_CPU_Control *cpu_self = _Per_CPU_Get(); Thread_Control *heir; - scheduled->is_scheduled = true; - victim->is_scheduled = false; + _Scheduler_SMP_Node_change_state( + scheduled_node, + SCHEDULER_SMP_NODE_SCHEDULED + ); _Assert( _ISR_Get_level() != 0 ); @@ -160,10 +191,10 @@ static inline void _Scheduler_SMP_Enqueue_ordered( Scheduler_SMP_Move move_from_scheduled_to_ready ) { - if ( thread->is_in_the_air ) { - Thread_Control *highest_ready = ( *get_highest_ready )( self ); + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); - thread->is_in_the_air = false; + if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) { + Thread_Control *highest_ready = ( *get_highest_ready )( self ); /* * The thread has been extracted from the scheduled chain. We have to @@ -175,13 +206,12 @@ static inline void _Scheduler_SMP_Enqueue_ordered( highest_ready != NULL && !( *order )( &thread->Object.Node, &highest_ready->Object.Node ) ) { + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY ); _Scheduler_SMP_Allocate_processor( self, highest_ready, thread ); - ( *insert_ready )( self, thread ); ( *move_from_ready_to_scheduled )( self, highest_ready ); } else { - thread->is_scheduled = true; - + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_SCHEDULED ); ( *insert_scheduled )( self, thread ); } } else { @@ -195,11 +225,18 @@ static inline void _Scheduler_SMP_Enqueue_ordered( lowest_scheduled != NULL && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) { - _Scheduler_SMP_Allocate_processor( self, thread, lowest_scheduled ); + Scheduler_SMP_Node *lowest_scheduled_node = + _Scheduler_SMP_Node_get( lowest_scheduled ); + _Scheduler_SMP_Node_change_state( + lowest_scheduled_node, + SCHEDULER_SMP_NODE_READY + ); + _Scheduler_SMP_Allocate_processor( self, thread, lowest_scheduled ); ( *insert_scheduled )( self, thread ); ( *move_from_scheduled_to_ready )( self, lowest_scheduled ); } else { + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY ); ( *insert_ready )( self, thread ); } } @@ -226,8 +263,10 @@ static inline void _Scheduler_SMP_Schedule( Scheduler_SMP_Move move_from_ready_to_scheduled ) { - if ( thread->is_in_the_air ) { - thread->is_in_the_air = false; + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + + if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) { + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED ); _Scheduler_SMP_Schedule_highest_ready( self, @@ -295,7 +334,10 @@ static inline void _Scheduler_SMP_Start_idle( Per_CPU_Control *cpu ) { - thread->is_scheduled = true; + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + + node->state = SCHEDULER_SMP_NODE_SCHEDULED; + _Thread_Set_CPU( thread, cpu ); _Chain_Append_unprotected( &self->Scheduled, &thread->Object.Node ); } diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 248ae96850..0deeea065f 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -39,6 +39,8 @@ struct Scheduler_Control; +struct Scheduler_Node; + #ifdef __cplusplus extern "C" { #endif @@ -479,31 +481,6 @@ struct Thread_Control_struct { bool is_preemptible; #if defined(RTEMS_SMP) /** - * @brief This field is true if the thread is scheduled. - * - * A thread is scheduled if it is ready and the scheduler allocated a - * processor for it. A scheduled thread is assigned to exactly one - * processor. There are exactly processor count scheduled threads in the - * system. - */ - bool is_scheduled; - - /** - * @brief This field is true if the thread is in the air. - * - * A thread is in the air if it has an allocated processor (it is an - * executing or heir thread on exactly one processor) and it is not a member - * of the scheduled chain. The extract operation on a scheduled thread will - * produce threads in the air (see also _Thread_Set_transient()). The next - * enqueue or schedule operation will decide what to do based on this state - * indication. It can either place the thread back on the scheduled chain - * and the thread can keep its allocated processor, or it can take the - * processor away from the thread and give the processor to another thread of - * higher priority. - */ - bool is_in_the_air; - - /** * @brief The scheduler of this thread. */ const struct Scheduler_Control *scheduler; @@ -530,8 +507,10 @@ struct Thread_Control_struct { */ Thread_CPU_usage_t cpu_time_used; - /** This pointer holds per-thread data for the scheduler and ready queue. */ - void *scheduler_info; + /** + * @brief The scheduler node of this thread for the real scheduler. + */ + struct Scheduler_Node *scheduler_node; #ifdef RTEMS_SMP /** diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index efbe37dbfc..d00e1374c6 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -191,6 +191,10 @@ $(PROJECT_INCLUDE)/rtems/score/schedulercbs.h: include/rtems/score/schedulercbs. $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulercbs.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulercbs.h +$(PROJECT_INCLUDE)/rtems/score/schedulercbsimpl.h: include/rtems/score/schedulercbsimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulercbsimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulercbsimpl.h + $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h: include/rtems/score/scheduleredf.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h diff --git a/cpukit/score/src/schedulercbs.c b/cpukit/score/src/schedulercbs.c index 54312b2ca6..e2f34d4c82 100644 --- a/cpukit/score/src/schedulercbs.c +++ b/cpukit/score/src/schedulercbs.c @@ -18,7 +18,7 @@ #include "config.h" #endif -#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulercbsimpl.h> #include <rtems/score/threadimpl.h> #include <rtems/score/wkspace.h> @@ -27,7 +27,7 @@ void _Scheduler_CBS_Budget_callout( ) { Priority_Control new_priority; - Scheduler_CBS_Per_thread *sched_info; + Scheduler_CBS_Node *node; Scheduler_CBS_Server_id server_id; /* Put violating task to background until the end of period. */ @@ -38,13 +38,13 @@ void _Scheduler_CBS_Budget_callout( _Thread_Change_priority(the_thread, new_priority, true); /* Invoke callback function if any. */ - sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; - if ( sched_info->cbs_server->cbs_budget_overrun ) { + node = _Scheduler_CBS_Node_get( the_thread ); + if ( node->cbs_server->cbs_budget_overrun ) { _Scheduler_CBS_Get_server_id( - sched_info->cbs_server->task_id, + node->cbs_server->task_id, &server_id ); - sched_info->cbs_server->cbs_budget_overrun( server_id ); + node->cbs_server->cbs_budget_overrun( server_id ); } } diff --git a/cpukit/score/src/schedulercbsallocate.c b/cpukit/score/src/schedulercbsallocate.c index a6f89c35a9..6a29088eb6 100644 --- a/cpukit/score/src/schedulercbsallocate.c +++ b/cpukit/score/src/schedulercbsallocate.c @@ -18,25 +18,20 @@ #include "config.h" #endif -#include <rtems/system.h> -#include <rtems/config.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/scheduleredf.h> -#include <rtems/score/schedulercbs.h> -#include <rtems/score/wkspace.h> +#include <rtems/score/schedulercbsimpl.h> bool _Scheduler_CBS_Allocate( const Scheduler_Control *scheduler, Thread_Control *the_thread ) { - Scheduler_CBS_Per_thread *schinfo = the_thread->scheduler_info; + Scheduler_CBS_Node *node = _Scheduler_CBS_Node_get( the_thread ); (void) scheduler; - schinfo->edf_per_thread.thread = the_thread; - schinfo->edf_per_thread.queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN; - schinfo->cbs_server = NULL; + node->Base.thread = the_thread; + node->Base.queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN; + node->cbs_server = NULL; return true; } diff --git a/cpukit/score/src/schedulercbsattachthread.c b/cpukit/score/src/schedulercbsattachthread.c index 43bf92da66..3892e89aae 100644 --- a/cpukit/score/src/schedulercbsattachthread.c +++ b/cpukit/score/src/schedulercbsattachthread.c @@ -18,7 +18,7 @@ #include "config.h" #endif -#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulercbsimpl.h> #include <rtems/score/threadimpl.h> int _Scheduler_CBS_Attach_thread ( @@ -43,18 +43,16 @@ int _Scheduler_CBS_Attach_thread ( the_thread = _Thread_Get(task_id, &location); /* The routine _Thread_Get may disable dispatch and not enable again. */ if ( the_thread ) { - Scheduler_CBS_Per_thread *sched_info; - - sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; + Scheduler_CBS_Node *node = _Scheduler_CBS_Node_get( the_thread ); /* Thread is already attached to a server. */ - if ( sched_info->cbs_server ) { + if ( node->cbs_server ) { _Objects_Put( &the_thread->Object ); return SCHEDULER_CBS_ERROR_FULL; } _Scheduler_CBS_Server_list[server_id].task_id = task_id; - sched_info->cbs_server = &_Scheduler_CBS_Server_list[server_id]; + node->cbs_server = &_Scheduler_CBS_Server_list[server_id]; the_thread->budget_callout = _Scheduler_CBS_Budget_callout; the_thread->budget_algorithm = THREAD_CPU_BUDGET_ALGORITHM_CALLOUT; diff --git a/cpukit/score/src/schedulercbsdetachthread.c b/cpukit/score/src/schedulercbsdetachthread.c index 0f77cdf10e..6d634ef59f 100644 --- a/cpukit/score/src/schedulercbsdetachthread.c +++ b/cpukit/score/src/schedulercbsdetachthread.c @@ -19,7 +19,7 @@ #include "config.h" #endif -#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulercbsimpl.h> #include <rtems/score/threadimpl.h> int _Scheduler_CBS_Detach_thread ( @@ -29,7 +29,6 @@ int _Scheduler_CBS_Detach_thread ( { Objects_Locations location; Thread_Control *the_thread; - Scheduler_CBS_Per_thread *sched_info; if ( server_id >= _Scheduler_CBS_Maximum_servers ) return SCHEDULER_CBS_ERROR_INVALID_PARAMETER; @@ -43,9 +42,10 @@ int _Scheduler_CBS_Detach_thread ( the_thread = _Thread_Get(task_id, &location); /* The routine _Thread_Get may disable dispatch and not enable again. */ if ( the_thread ) { + Scheduler_CBS_Node *node = _Scheduler_CBS_Node_get( the_thread ); + _Scheduler_CBS_Server_list[server_id].task_id = -1; - sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; - sched_info->cbs_server = NULL; + node->cbs_server = NULL; the_thread->budget_algorithm = the_thread->Start.budget_algorithm; the_thread->budget_callout = the_thread->Start.budget_callout; diff --git a/cpukit/score/src/schedulercbsreleasejob.c b/cpukit/score/src/schedulercbsreleasejob.c index c5ac572a61..eec930a6c1 100644 --- a/cpukit/score/src/schedulercbsreleasejob.c +++ b/cpukit/score/src/schedulercbsreleasejob.c @@ -19,7 +19,7 @@ #include "config.h" #endif -#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulercbsimpl.h> #include <rtems/score/threadimpl.h> #include <rtems/score/watchdogimpl.h> @@ -29,11 +29,9 @@ void _Scheduler_CBS_Release_job( uint32_t deadline ) { - Priority_Control new_priority; - Scheduler_CBS_Per_thread *sched_info = - (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; - Scheduler_CBS_Server *serv_info = - (Scheduler_CBS_Server *) sched_info->cbs_server; + Scheduler_CBS_Node *node = _Scheduler_CBS_Node_get( the_thread ); + Scheduler_CBS_Server *serv_info = node->cbs_server; + Priority_Control new_priority; if (deadline) { /* Initializing or shifting deadline. */ diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c index 030cc85c68..411e6cef27 100644 --- a/cpukit/score/src/schedulercbsunblock.c +++ b/cpukit/score/src/schedulercbsunblock.c @@ -19,7 +19,7 @@ #include "config.h" #endif -#include <rtems/score/schedulercbs.h> +#include <rtems/score/schedulercbsimpl.h> #include <rtems/score/schedulerimpl.h> #include <rtems/score/threadimpl.h> #include <rtems/score/watchdogimpl.h> @@ -29,16 +29,13 @@ void _Scheduler_CBS_Unblock( Thread_Control *the_thread ) { - Scheduler_CBS_Per_thread *sched_info; - Scheduler_CBS_Server *serv_info; - Priority_Control new_priority; + Scheduler_CBS_Node *node = _Scheduler_CBS_Node_get( the_thread ); + Scheduler_CBS_Server *serv_info = node->cbs_server; + Priority_Control new_priority; _Scheduler_EDF_Enqueue( scheduler, the_thread ); /* TODO: flash critical section? */ - sched_info = (Scheduler_CBS_Per_thread *) the_thread->scheduler_info; - serv_info = (Scheduler_CBS_Server *) sched_info->cbs_server; - /* * Late unblock rule for deadline-driven tasks. The remaining time to * deadline must be sufficient to serve the remaining computation time diff --git a/cpukit/score/src/scheduleredf.c b/cpukit/score/src/scheduleredf.c index 4d1aa62d08..010d053949 100644 --- a/cpukit/score/src/scheduleredf.c +++ b/cpukit/score/src/scheduleredf.c @@ -27,9 +27,9 @@ static int _Scheduler_EDF_RBTree_compare_function ) { Priority_Control value1 = _RBTree_Container_of - (n1,Scheduler_EDF_Per_thread,Node)->thread->current_priority; + (n1,Scheduler_EDF_Node,Node)->thread->current_priority; Priority_Control value2 = _RBTree_Container_of - (n2,Scheduler_EDF_Per_thread,Node)->thread->current_priority; + (n2,Scheduler_EDF_Node,Node)->thread->current_priority; /* * This function compares only numbers for the red-black tree, diff --git a/cpukit/score/src/scheduleredfallocate.c b/cpukit/score/src/scheduleredfallocate.c index 3dc9dd5070..f9aaa57b8a 100644 --- a/cpukit/score/src/scheduleredfallocate.c +++ b/cpukit/score/src/scheduleredfallocate.c @@ -18,24 +18,19 @@ #include "config.h" #endif -#include <rtems/system.h> -#include <rtems/config.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/scheduleredf.h> -#include <rtems/score/wkspace.h> +#include <rtems/score/scheduleredfimpl.h> bool _Scheduler_EDF_Allocate( const Scheduler_Control *scheduler, Thread_Control *the_thread ) { - Scheduler_EDF_Per_thread *schinfo = the_thread->scheduler_info; + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); (void) scheduler; - schinfo = (Scheduler_EDF_Per_thread *)(the_thread->scheduler_info); - schinfo->thread = the_thread; - schinfo->queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN; + node->thread = the_thread; + node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN; return true; } diff --git a/cpukit/score/src/scheduleredfenqueue.c b/cpukit/score/src/scheduleredfenqueue.c index 38e67eb7a7..8973d8b32c 100644 --- a/cpukit/score/src/scheduleredfenqueue.c +++ b/cpukit/score/src/scheduleredfenqueue.c @@ -27,10 +27,8 @@ void _Scheduler_EDF_Enqueue( { Scheduler_EDF_Context *context = _Scheduler_EDF_Get_context( scheduler ); - Scheduler_EDF_Per_thread *sched_info = - (Scheduler_EDF_Per_thread*) the_thread->scheduler_info; - RBTree_Node *node = &(sched_info->Node); + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); - _RBTree_Insert( &context->Ready, node ); - sched_info->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES; + _RBTree_Insert( &context->Ready, &node->Node ); + node->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES; } diff --git a/cpukit/score/src/scheduleredfextract.c b/cpukit/score/src/scheduleredfextract.c index 02c47afb06..94fde0a05c 100644 --- a/cpukit/score/src/scheduleredfextract.c +++ b/cpukit/score/src/scheduleredfextract.c @@ -27,10 +27,8 @@ void _Scheduler_EDF_Extract( { Scheduler_EDF_Context *context = _Scheduler_EDF_Get_context( scheduler ); - Scheduler_EDF_Per_thread *sched_info = - (Scheduler_EDF_Per_thread*) the_thread->scheduler_info; - RBTree_Node *node = &(sched_info->Node); + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); - _RBTree_Extract( &context->Ready, node ); - sched_info->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY; + _RBTree_Extract( &context->Ready, &node->Node ); + node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY; } diff --git a/cpukit/score/src/scheduleredfupdate.c b/cpukit/score/src/scheduleredfupdate.c index 88d6d9d7d4..99a3e0e3f6 100644 --- a/cpukit/score/src/scheduleredfupdate.c +++ b/cpukit/score/src/scheduleredfupdate.c @@ -18,28 +18,22 @@ #include "config.h" #endif -#include <rtems/system.h> -#include <rtems/config.h> -#include <rtems/score/priority.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/scheduleredf.h> -#include <rtems/score/thread.h> +#include <rtems/score/scheduleredfimpl.h> void _Scheduler_EDF_Update( const Scheduler_Control *scheduler, Thread_Control *the_thread ) { - Scheduler_EDF_Per_thread *sched_info = - (Scheduler_EDF_Per_thread*)the_thread->scheduler_info; + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); (void) scheduler; - if (sched_info->queue_state == SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN) { + if (node->queue_state == SCHEDULER_EDF_QUEUE_STATE_NEVER_HAS_BEEN) { /* Shifts the priority to the region of background tasks. */ the_thread->Start.initial_priority |= (SCHEDULER_EDF_PRIO_MSB); the_thread->real_priority = the_thread->Start.initial_priority; the_thread->current_priority = the_thread->Start.initial_priority; - sched_info->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY; + node->queue_state = SCHEDULER_EDF_QUEUE_STATE_NOT_PRESENTLY; } } diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c index 8f8786ad1d..9eb07825fe 100644 --- a/cpukit/score/src/scheduleredfyield.c +++ b/cpukit/score/src/scheduleredfyield.c @@ -28,20 +28,17 @@ void _Scheduler_EDF_Yield( { Scheduler_EDF_Context *context = _Scheduler_EDF_Get_context( scheduler ); + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); ISR_Level level; - Scheduler_EDF_Per_thread *thread_info = - (Scheduler_EDF_Per_thread *) the_thread->scheduler_info; - RBTree_Node *thread_node = &(thread_info->Node); - _ISR_Disable( level ); /* * The RBTree has more than one node, enqueue behind the tasks * with the same priority in case there are such ones. */ - _RBTree_Extract( &context->Ready, thread_node ); - _RBTree_Insert( &context->Ready, thread_node ); + _RBTree_Extract( &context->Ready, &node->Node ); + _RBTree_Insert( &context->Ready, &node->Node ); _ISR_Flash( level ); diff --git a/cpukit/score/src/schedulerpriorityaffinitysmp.c b/cpukit/score/src/schedulerpriorityaffinitysmp.c index 0ea4336321..0d9525d894 100644 --- a/cpukit/score/src/schedulerpriorityaffinitysmp.c +++ b/cpukit/score/src/schedulerpriorityaffinitysmp.c @@ -25,10 +25,11 @@ #include <rtems/score/wkspace.h> #include <rtems/score/cpusetimpl.h> -RTEMS_INLINE_ROUTINE Scheduler_priority_affinity_SMP_Per_thread * -_Scheduler_priority_affinity_Get_scheduler_info( Thread_Control *thread ) +static Scheduler_priority_affinity_SMP_Node * +_Scheduler_priority_affinity_Node_get( Thread_Control *thread ) { - return ( Scheduler_priority_affinity_SMP_Per_thread * ) thread->scheduler_info; + return ( Scheduler_priority_affinity_SMP_Node * ) + _Scheduler_Node_get( thread ); } bool _Scheduler_priority_affinity_SMP_Allocate( @@ -36,11 +37,13 @@ bool _Scheduler_priority_affinity_SMP_Allocate( Thread_Control *the_thread ) { - Scheduler_priority_affinity_SMP_Per_thread *info = - the_thread->scheduler_info; + Scheduler_priority_affinity_SMP_Node *node = + _Scheduler_priority_affinity_Node_get( the_thread ); - info->Affinity = *_CPU_set_Default(); - info->Affinity.set = &info->Affinity.preallocated; + _Scheduler_SMP_Node_initialize( &node->Base.Base ); + + node->Affinity = *_CPU_set_Default(); + node->Affinity.set = &node->Affinity.preallocated; return true; } @@ -52,16 +55,16 @@ bool _Scheduler_priority_affinity_SMP_Get_affinity( cpu_set_t *cpuset ) { - Scheduler_priority_affinity_SMP_Per_thread *info = - _Scheduler_priority_affinity_Get_scheduler_info(thread); + Scheduler_priority_affinity_SMP_Node *node = + _Scheduler_priority_affinity_Node_get(thread); (void) scheduler; - if ( info->Affinity.setsize != cpusetsize ) { + if ( node->Affinity.setsize != cpusetsize ) { return false; } - CPU_COPY( cpuset, info->Affinity.set ); + CPU_COPY( cpuset, node->Affinity.set ); return true; } @@ -72,8 +75,8 @@ bool _Scheduler_priority_affinity_SMP_Set_affinity( cpu_set_t *cpuset ) { - Scheduler_priority_affinity_SMP_Per_thread *info = - _Scheduler_priority_affinity_Get_scheduler_info(thread); + Scheduler_priority_affinity_SMP_Node *node = + _Scheduler_priority_affinity_Node_get(thread); (void) scheduler; @@ -81,7 +84,7 @@ bool _Scheduler_priority_affinity_SMP_Set_affinity( return false; } - CPU_COPY( info->Affinity.set, cpuset ); + CPU_COPY( node->Affinity.set, cpuset ); return true; } diff --git a/cpukit/score/src/schedulerpriorityenqueue.c b/cpukit/score/src/schedulerpriorityenqueue.c index e3f2be6061..aa901cc978 100644 --- a/cpukit/score/src/schedulerpriorityenqueue.c +++ b/cpukit/score/src/schedulerpriorityenqueue.c @@ -27,6 +27,11 @@ void _Scheduler_priority_Enqueue( { Scheduler_priority_Context *context = _Scheduler_priority_Get_context( scheduler ); + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); - _Scheduler_priority_Ready_queue_enqueue( the_thread, &context->Bit_map ); + _Scheduler_priority_Ready_queue_enqueue( + the_thread, + &node->Ready_queue, + &context->Bit_map + ); } diff --git a/cpukit/score/src/schedulerpriorityenqueuefirst.c b/cpukit/score/src/schedulerpriorityenqueuefirst.c index 0d197065a0..1714fe57f0 100644 --- a/cpukit/score/src/schedulerpriorityenqueuefirst.c +++ b/cpukit/score/src/schedulerpriorityenqueuefirst.c @@ -27,9 +27,11 @@ void _Scheduler_priority_Enqueue_first( { Scheduler_priority_Context *context = _Scheduler_priority_Get_context( scheduler ); + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); _Scheduler_priority_Ready_queue_enqueue_first( the_thread, + &node->Ready_queue, &context->Bit_map ); } diff --git a/cpukit/score/src/schedulerprioritysmp.c b/cpukit/score/src/schedulerprioritysmp.c index 025d9601fd..263bc8746d 100644 --- a/cpukit/score/src/schedulerprioritysmp.c +++ b/cpukit/score/src/schedulerprioritysmp.c @@ -1,9 +1,9 @@ /** * @file * - * @brief Deterministic Priority SMP Scheduler Implementation + * @ingroup ScoreSchedulerPrioritySMP * - * @ingroup ScoreSchedulerSMP + * @brief Deterministic Priority SMP Scheduler Implementation */ /* @@ -43,6 +43,13 @@ _Scheduler_priority_SMP_Self_from_SMP_base( Scheduler_SMP_Context *smp_base ) - offsetof( Scheduler_priority_SMP_Context, Base ) ); } +static Scheduler_priority_SMP_Node *_Scheduler_priority_SMP_Node_get( + Thread_Control *thread +) +{ + return (Scheduler_priority_SMP_Node *) _Scheduler_Node_get( thread ); +} + void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler ) { Scheduler_priority_SMP_Context *self = @@ -53,6 +60,18 @@ void _Scheduler_priority_SMP_Initialize( const Scheduler_Control *scheduler ) _Scheduler_priority_Ready_queue_initialize( &self->Ready[ 0 ] ); } +bool _Scheduler_priority_SMP_Allocate( + const Scheduler_Control *scheduler, + Thread_Control *thread +) +{ + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + + _Scheduler_SMP_Node_initialize( node ); + + return true; +} + void _Scheduler_priority_SMP_Update( const Scheduler_Control *scheduler, Thread_Control *thread @@ -60,9 +79,12 @@ void _Scheduler_priority_SMP_Update( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Get_context( scheduler ); + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( thread ); - _Scheduler_priority_Update_body( + _Scheduler_priority_Ready_queue_update( thread, + &node->Ready_queue, &self->Bit_map, &self->Ready[ 0 ] ); @@ -93,10 +115,13 @@ static void _Scheduler_priority_SMP_Move_from_scheduled_to_ready( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Self_from_SMP_base( smp_base ); + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( scheduled_to_ready ); _Chain_Extract_unprotected( &scheduled_to_ready->Object.Node ); _Scheduler_priority_Ready_queue_enqueue_first( scheduled_to_ready, + &node->Ready_queue, &self->Bit_map ); } @@ -108,9 +133,12 @@ static void _Scheduler_priority_SMP_Move_from_ready_to_scheduled( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Self_from_SMP_base( smp_base ); + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( ready_to_scheduled ); _Scheduler_priority_Ready_queue_extract( ready_to_scheduled, + &node->Ready_queue, &self->Bit_map ); _Scheduler_simple_Insert_priority_fifo( @@ -126,8 +154,14 @@ static void _Scheduler_priority_SMP_Insert_ready_lifo( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Self_from_SMP_base( smp_base ); + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( thread ); - _Scheduler_priority_Ready_queue_enqueue( thread, &self->Bit_map ); + _Scheduler_priority_Ready_queue_enqueue( + thread, + &node->Ready_queue, + &self->Bit_map + ); } static void _Scheduler_priority_SMP_Insert_ready_fifo( @@ -137,8 +171,14 @@ static void _Scheduler_priority_SMP_Insert_ready_fifo( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Self_from_SMP_base( smp_base ); + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( thread ); - _Scheduler_priority_Ready_queue_enqueue_first( thread, &self->Bit_map ); + _Scheduler_priority_Ready_queue_enqueue_first( + thread, + &node->Ready_queue, + &self->Bit_map + ); } static void _Scheduler_priority_SMP_Do_extract( @@ -148,15 +188,25 @@ static void _Scheduler_priority_SMP_Do_extract( { Scheduler_priority_SMP_Context *self = _Scheduler_priority_SMP_Self_from_SMP_base( smp_base ); - bool is_scheduled = thread->is_scheduled; - - thread->is_in_the_air = is_scheduled; - thread->is_scheduled = false; + Scheduler_priority_SMP_Node *node = + _Scheduler_priority_SMP_Node_get( thread ); - if ( is_scheduled ) { + if ( node->Base.state == SCHEDULER_SMP_NODE_SCHEDULED ) { + _Scheduler_SMP_Node_change_state( + &node->Base, + SCHEDULER_SMP_NODE_IN_THE_AIR + ); _Chain_Extract_unprotected( &thread->Object.Node ); } else { - _Scheduler_priority_Ready_queue_extract( thread, &self->Bit_map ); + _Scheduler_SMP_Node_change_state( + &node->Base, + SCHEDULER_SMP_NODE_BLOCKED + ); + _Scheduler_priority_Ready_queue_extract( + thread, + &node->Ready_queue, + &self->Bit_map + ); } } diff --git a/cpukit/score/src/schedulerpriorityunblock.c b/cpukit/score/src/schedulerpriorityunblock.c index f5482a8229..e83bff1abf 100644 --- a/cpukit/score/src/schedulerpriorityunblock.c +++ b/cpukit/score/src/schedulerpriorityunblock.c @@ -29,8 +29,13 @@ void _Scheduler_priority_Unblock ( { Scheduler_priority_Context *context = _Scheduler_priority_Get_context( scheduler ); + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); - _Scheduler_priority_Ready_queue_enqueue( the_thread, &context->Bit_map ); + _Scheduler_priority_Ready_queue_enqueue( + the_thread, + &node->Ready_queue, + &context->Bit_map + ); /* TODO: flash critical section? */ diff --git a/cpukit/score/src/schedulerpriorityupdate.c b/cpukit/score/src/schedulerpriorityupdate.c index c906c346b4..8a22ee662d 100644 --- a/cpukit/score/src/schedulerpriorityupdate.c +++ b/cpukit/score/src/schedulerpriorityupdate.c @@ -27,9 +27,11 @@ void _Scheduler_priority_Update( { Scheduler_priority_Context *context = _Scheduler_priority_Get_context( scheduler ); + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); - _Scheduler_priority_Update_body( + _Scheduler_priority_Ready_queue_update( the_thread, + &node->Ready_queue, &context->Bit_map, &context->Ready[ 0 ] ); diff --git a/cpukit/score/src/schedulerpriorityyield.c b/cpukit/score/src/schedulerpriorityyield.c index 63b344ace7..f2aeada660 100644 --- a/cpukit/score/src/schedulerpriorityyield.c +++ b/cpukit/score/src/schedulerpriorityyield.c @@ -27,9 +27,8 @@ void _Scheduler_priority_Yield( Thread_Control *the_thread ) { - Scheduler_priority_Per_thread *sched_info_of_thread = - _Scheduler_priority_Get_scheduler_info( the_thread ); - Chain_Control *ready_chain = sched_info_of_thread->ready_chain; + Scheduler_priority_Node *node = _Scheduler_priority_Node_get( the_thread ); + Chain_Control *ready_chain = node->Ready_queue.ready_chain; ISR_Level level; (void) scheduler; diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c index 5448d5d3de..7fe2fd7943 100644 --- a/cpukit/score/src/schedulersimplesmp.c +++ b/cpukit/score/src/schedulersimplesmp.c @@ -3,7 +3,7 @@ * * @brief Simple SMP Scheduler Implementation * - * @ingroup ScoreSchedulerSMP + * @ingroup ScoreSchedulerSMPSimple */ /* @@ -44,6 +44,18 @@ void _Scheduler_simple_smp_Initialize( const Scheduler_Control *scheduler ) _Chain_Initialize_empty( &self->Ready ); } +bool _Scheduler_simple_smp_Allocate( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +) +{ + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( the_thread ); + + _Scheduler_SMP_Node_initialize( node ); + + return true; +} + static Thread_Control *_Scheduler_simple_smp_Get_highest_ready( Scheduler_SMP_Context *smp_base ) @@ -122,10 +134,15 @@ static void _Scheduler_simple_smp_Do_extract( Thread_Control *thread ) { + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + (void) smp_base; - thread->is_in_the_air = thread->is_scheduled; - thread->is_scheduled = false; + if ( node->state == SCHEDULER_SMP_NODE_SCHEDULED ) { + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_IN_THE_AIR ); + } else { + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED ); + } _Chain_Extract_unprotected( &thread->Object.Node ); } diff --git a/cpukit/score/src/schedulersmpvalidstatechanges.c b/cpukit/score/src/schedulersmpvalidstatechanges.c new file mode 100644 index 0000000000..61f6a7e2d5 --- /dev/null +++ b/cpukit/score/src/schedulersmpvalidstatechanges.c @@ -0,0 +1,39 @@ +/** + * @file + * + * @ingroup ScoreSchedulerSMP + * + * @brief SMP Scheduler Implementation + */ + +/* + * Copyright (c) 2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * 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. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/score/schedulerpriorityimpl.h> + +/* + * Table with all valid state transitions. It is used in + * _Scheduler_SMP_Node_change_state() in case RTEMS_DEBUG is defined. + */ +const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ] = { + /* BLOCKED SCHEDULED READY IN THE AIR */ + /* BLOCKED */ { false, true, true, false }, + /* SCHEDULED */ { false, false, true, true }, + /* READY */ { true, true, false, false }, + /* IN THE AIR */ { true, true, true, false } +}; diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index 2beaed4563..b65628d1eb 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -181,8 +181,6 @@ bool _Thread_Initialize( the_thread->Start.isr_level = isr_level; #if defined(RTEMS_SMP) - the_thread->is_scheduled = false; - the_thread->is_in_the_air = false; the_thread->scheduler = scheduler; _CPU_Context_Set_is_executing( &the_thread->Registers, false ); #endif diff --git a/testsuites/sptests/spsize/size.c b/testsuites/sptests/spsize/size.c index dc1e55b10d..9e4823e1b1 100644 --- a/testsuites/sptests/spsize/size.c +++ b/testsuites/sptests/spsize/size.c @@ -87,7 +87,7 @@ void print_formula(void); /* Priority scheduling per-thread consumption. Gets * included in the PER_TASK consumption. */ -#define SCHEDULER_TASK_WKSP (sizeof(Scheduler_priority_Per_thread)) +#define SCHEDULER_TASK_WKSP (sizeof(Scheduler_priority_Node)) /* Priority scheduling workspace consumption * |