From beab7329fca655c93743fbb590d00bb4ea5a6d78 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 13 May 2014 16:03:05 +0200 Subject: score: Introduce scheduler nodes Rename scheduler per-thread information into scheduler nodes using Scheduler_Node as the base type. Use inheritance for specialized schedulers. Move the scheduler specific states from the thread control block into the scheduler node structure. Validate the SMP scheduler node state transitions in case RTEMS_DEBUG is defined. --- cpukit/sapi/include/confdefs.h | 20 ++-- cpukit/score/Makefile.am | 2 + cpukit/score/include/rtems/score/scheduler.h | 9 ++ cpukit/score/include/rtems/score/schedulercbs.h | 4 +- .../score/include/rtems/score/schedulercbsimpl.h | 52 ++++++++++ cpukit/score/include/rtems/score/scheduleredf.h | 9 +- .../score/include/rtems/score/scheduleredfimpl.h | 13 ++- cpukit/score/include/rtems/score/schedulerimpl.h | 7 ++ .../score/include/rtems/score/schedulerpriority.h | 19 +++- .../rtems/score/schedulerpriorityaffinitysmp.h | 15 +-- .../include/rtems/score/schedulerpriorityimpl.h | 112 ++++++++++++--------- .../include/rtems/score/schedulerprioritysmp.h | 29 +++++- .../score/include/rtems/score/schedulersimplesmp.h | 7 +- cpukit/score/include/rtems/score/schedulersmp.h | 66 ++++++++++++ .../score/include/rtems/score/schedulersmpimpl.h | 66 +++++++++--- cpukit/score/include/rtems/score/thread.h | 33 ++---- cpukit/score/preinstall.am | 4 + cpukit/score/src/schedulercbs.c | 12 +-- cpukit/score/src/schedulercbsallocate.c | 15 +-- cpukit/score/src/schedulercbsattachthread.c | 10 +- cpukit/score/src/schedulercbsdetachthread.c | 8 +- cpukit/score/src/schedulercbsreleasejob.c | 10 +- cpukit/score/src/schedulercbsunblock.c | 11 +- cpukit/score/src/scheduleredf.c | 4 +- cpukit/score/src/scheduleredfallocate.c | 13 +-- cpukit/score/src/scheduleredfenqueue.c | 8 +- cpukit/score/src/scheduleredfextract.c | 8 +- cpukit/score/src/scheduleredfupdate.c | 14 +-- cpukit/score/src/scheduleredfyield.c | 9 +- cpukit/score/src/schedulerpriorityaffinitysmp.c | 31 +++--- cpukit/score/src/schedulerpriorityenqueue.c | 7 +- cpukit/score/src/schedulerpriorityenqueuefirst.c | 2 + cpukit/score/src/schedulerprioritysmp.c | 72 +++++++++++-- cpukit/score/src/schedulerpriorityunblock.c | 7 +- cpukit/score/src/schedulerpriorityupdate.c | 4 +- cpukit/score/src/schedulerpriorityyield.c | 5 +- cpukit/score/src/schedulersimplesmp.c | 23 ++++- cpukit/score/src/schedulersmpvalidstatechanges.c | 39 +++++++ cpukit/score/src/threadinitialize.c | 2 - testsuites/sptests/spsize/size.c | 2 +- 40 files changed, 553 insertions(+), 230 deletions(-) create mode 100644 cpukit/score/include/rtems/score/schedulercbsimpl.h create mode 100644 cpukit/score/src/schedulersmpvalidstatechanges.c 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. */ @@ -156,6 +158,13 @@ struct Scheduler_Control { uint32_t name; }; +/** + * @brief Scheduler node for per-thread data. + */ +struct Scheduler_Node { + /* No fields yet */ +}; + /** * @brief Registered schedulers. * 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 + * + * + * 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 +#include + +#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,9 +91,14 @@ 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. */ @@ -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,12 +47,32 @@ 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. */ @@ -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 @@ -478,31 +480,6 @@ struct Thread_Control_struct { /** This field is true if the thread is preemptible. */ 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. */ @@ -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 +#include #include #include @@ -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 -#include -#include -#include -#include -#include +#include 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 +#include #include 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 +#include #include 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 +#include #include #include @@ -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 +#include #include #include #include @@ -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 -#include -#include -#include -#include +#include 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 -#include -#include -#include -#include -#include +#include 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 #include -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 + * + * + * 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 + +/* + * 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 * -- cgit v1.2.3