diff options
Diffstat (limited to 'cpukit/score/include/rtems')
-rw-r--r-- | cpukit/score/include/rtems/score/scheduler.h | 9 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulercbs.h | 4 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulercbsimpl.h | 52 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/scheduleredf.h | 9 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/scheduleredfimpl.h | 13 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerimpl.h | 7 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerpriority.h | 19 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h | 15 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerpriorityimpl.h | 112 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulerprioritysmp.h | 29 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulersimplesmp.h | 7 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulersmp.h | 66 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/schedulersmpimpl.h | 66 | ||||
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 33 |
14 files changed, 331 insertions, 110 deletions
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 /** |