Update #2556. --- cpukit/posix/src/killinfo.c | 5 +- cpukit/score/include/rtems/score/schedulerimpl.h | 17 +- cpukit/score/include/rtems/score/schedulernode.h | 40 ++++- cpukit/score/include/rtems/score/thread.h | 217 +++++++++++------------ cpukit/score/include/rtems/score/threadimpl.h | 6 - cpukit/score/src/thread.c | 1 + cpukit/score/src/threadmp.c | 11 ++ cpukit/score/src/threadqflush.c | 10 +- cpukit/score/src/threadqops.c | 69 +++++-- 9 files changed, 226 insertions(+), 150 deletions(-)
diff --git a/cpukit/posix/src/killinfo.c b/cpukit/posix/src/killinfo.c index b7f0354..2e7bacb 100644 --- a/cpukit/posix/src/killinfo.c +++ b/cpukit/posix/src/killinfo.c @@ -27,6 +27,7 @@ #include <rtems/posix/pthreadimpl.h> #include <rtems/posix/psignalimpl.h> #include <rtems/score/isr.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/statesimpl.h> #include <rtems/seterr.h> @@ -150,8 +151,10 @@ int _POSIX_signals_Send( for ( the_node = _Chain_First( the_chain ); !_Chain_Is_tail( the_chain, the_node ) ; the_node = the_node->next ) { + Scheduler_Node *scheduler_node; - the_thread = THREAD_CHAIN_NODE_TO_THREAD( the_node ); + scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( the_node ); + the_thread = _Scheduler_Node_get_owner( scheduler_node ); api = the_thread->API_Extensions[ THREAD_API_POSIX ]; #if defined(DEBUG_SIGNAL_PROCESSING) diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 1c5a697..0832360 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -785,13 +785,14 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize( Priority_Control priority ) { + node->owner = the_thread; + node->Priority.value = priority; node->Priority.prepend_it = false; #if defined(RTEMS_SMP) node->user = the_thread; node->help_state = SCHEDULER_HELP_YOURSELF; - node->owner = the_thread; node->idle = NULL; node->accepts_help = the_thread; _SMP_sequence_lock_Initialize( &node->Priority.Lock ); @@ -800,6 +801,13 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Node_do_initialize( #endif } +RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_owner( + const Scheduler_Node *node +) +{ + return node->owner; +} + RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Node_get_priority( Scheduler_Node *node, bool *prepend_it_p @@ -885,13 +893,6 @@ typedef void ( *Scheduler_Release_idle_thread )( Thread_Control *idle ); -RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_owner( - const Scheduler_Node *node -) -{ - return node->owner; -} - RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_idle( const Scheduler_Node *node ) diff --git a/cpukit/score/include/rtems/score/schedulernode.h b/cpukit/score/include/rtems/score/schedulernode.h index 6153624..63d86e6 100644 --- a/cpukit/score/include/rtems/score/schedulernode.h +++ b/cpukit/score/include/rtems/score/schedulernode.h @@ -123,11 +123,6 @@ typedef struct { Scheduler_Help_state help_state; /** - * @brief The thread owning this node. - */ - struct _Thread_Control *owner; - - /** * @brief The idle thread claimed by this node in case the help state is * SCHEDULER_HELP_ACTIVE_OWNER. * @@ -146,6 +141,35 @@ typedef struct { #endif /** + * @brief Thread wait support block. + */ + struct { + /** + * @brief Node for thread queues. + * + * Each scheduler node can be enqueued on a thread queue on behalf of the + * thread owning the scheduler node. The scheduler node reflects the + * priority of the thread within the corresponding scheduler instance. + */ + union { + /** + * @brief A node for chains. + */ + Chain_Node Chain; + + /** + * @brief A node for red-black trees. + */ + RBTree_Node RBTree; + } Node; + } Wait; + + /** + * @brief The thread owning this node. + */ + struct _Thread_Control *owner; + + /** * @brief The thread priority information used by the scheduler. * * The thread priority is manifest in two independent areas. One area is the @@ -181,6 +205,12 @@ typedef struct { } Priority; } Scheduler_Node; +#define SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node ) \ + RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.Chain ) + +#define SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( node ) \ + RTEMS_CONTAINER_OF( node, Scheduler_Node, Wait.Node.RBTree ) + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 19b52cd..a5faad3 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -210,6 +210,96 @@ typedef struct { void *tls_area; } Thread_Start_information; +#if defined(RTEMS_SMP) +/** + * @brief The thread state with respect to the scheduler. + */ +typedef enum { + /** + * @brief This thread is blocked with respect to the scheduler. + * + * This thread uses no scheduler nodes. + */ + THREAD_SCHEDULER_BLOCKED, + + /** + * @brief This thread is scheduled with respect to the scheduler. + * + * This thread executes using one of its scheduler nodes. This could be its + * own scheduler node or in case it owns resources taking part in the + * scheduler helping protocol a scheduler node of another thread. + */ + THREAD_SCHEDULER_SCHEDULED, + + /** + * @brief This thread is ready with respect to the scheduler. + * + * None of the scheduler nodes of this thread is scheduled. + */ + THREAD_SCHEDULER_READY +} Thread_Scheduler_state; +#endif + +/** + * @brief Thread scheduler control. + */ +typedef struct { +#if defined(RTEMS_SMP) + /** + * @brief The current scheduler state of this thread. + */ + Thread_Scheduler_state state; + + /** + * @brief The own scheduler control of this thread. + * + * This field is constant after initialization. + */ + const struct Scheduler_Control *own_control; + + /** + * @brief The scheduler control of this thread. + * + * The scheduler helping protocol may change this field. + */ + const struct Scheduler_Control *control; + + /** + * @brief The own scheduler node of this thread. + * + * This field is constant after initialization. It is used by change + * priority and ask for help operations. + */ + Scheduler_Node *own_node; +#endif + + /** + * @brief The scheduler node of this thread. + * + * On uni-processor configurations this field is constant after + * initialization. + * + * On SMP configurations the scheduler helping protocol may change this + * field. + */ + Scheduler_Node *node; + +#if defined(RTEMS_SMP) + /** + * @brief The processor assigned by the current scheduler. + */ + struct Per_CPU_Control *cpu; + +#if defined(RTEMS_DEBUG) + /** + * @brief The processor on which this thread executed the last time or is + * executing. + */ + struct Per_CPU_Control *debug_real_cpu; +#endif +#endif +} Thread_Scheduler_control; + /** * @brief Union type to hold a pointer to an immutable or a mutable object. * @@ -248,21 +338,6 @@ typedef unsigned int Thread_Wait_flags; * blocked and to return information to it. */ typedef struct { - /** - * @brief Node for thread queues. - */ - union { - /** - * @brief A node for chains. - */ - Chain_Node Chain; - - /** - * @brief A node for red-black trees. - */ - RBTree_Node RBTree; - } Node; - #if defined(RTEMS_MULTIPROCESSING) /* * @brief This field is the identifier of the remote object this thread is @@ -424,6 +499,11 @@ typedef struct { /** This field is the number of mutexes currently held by this proxy. */ uint32_t resource_count; + /** + * @brief Scheduler related control. + */ + Thread_Scheduler_control Scheduler; + /** This field is the blocking information for this proxy. */ Thread_Wait_information Wait; /** This field is the Watchdog used to manage proxy delays and timeouts. */ @@ -444,6 +524,12 @@ typedef struct { RBTree_Node Active; /** + * @brief The scheduler node providing the thread wait nodes used to enqueue + * this thread proxy on a thread queue. + */ + Scheduler_Node Scheduler_node; + + /** * @brief Provide thread queue heads for this thread proxy. * * The actual size of the thread queue heads depends on the application @@ -592,96 +678,6 @@ typedef struct { #endif } Thread_Life_control; -#if defined(RTEMS_SMP) -/** - * @brief The thread state with respect to the scheduler. - */ -typedef enum { - /** - * @brief This thread is blocked with respect to the scheduler. - * - * This thread uses no scheduler nodes. - */ - THREAD_SCHEDULER_BLOCKED, - - /** - * @brief This thread is scheduled with respect to the scheduler. - * - * This thread executes using one of its scheduler nodes. This could be its - * own scheduler node or in case it owns resources taking part in the - * scheduler helping protocol a scheduler node of another thread. - */ - THREAD_SCHEDULER_SCHEDULED, - - /** - * @brief This thread is ready with respect to the scheduler. - * - * None of the scheduler nodes of this thread is scheduled. - */ - THREAD_SCHEDULER_READY -} Thread_Scheduler_state; -#endif - -/** - * @brief Thread scheduler control. - */ -typedef struct { -#if defined(RTEMS_SMP) - /** - * @brief The current scheduler state of this thread. - */ - Thread_Scheduler_state state; - - /** - * @brief The own scheduler control of this thread. - * - * This field is constant after initialization. - */ - const struct Scheduler_Control *own_control; - - /** - * @brief The scheduler control of this thread. - * - * The scheduler helping protocol may change this field. - */ - const struct Scheduler_Control *control; - - /** - * @brief The own scheduler node of this thread. - * - * This field is constant after initialization. It is used by change - * priority and ask for help operations. - */ - Scheduler_Node *own_node; -#endif - - /** - * @brief The scheduler node of this thread. - * - * On uni-processor configurations this field is constant after - * initialization. - * - * On SMP configurations the scheduler helping protocol may change this - * field. - */ - Scheduler_Node *node; - -#if defined(RTEMS_SMP) - /** - * @brief The processor assigned by the current scheduler. - */ - struct Per_CPU_Control *cpu; - -#if defined(RTEMS_DEBUG) - /** - * @brief The processor on which this thread executed the last time or is - * executing. - */ - struct Per_CPU_Control *debug_real_cpu; -#endif -#endif -} Thread_Scheduler_control; - typedef struct { uint32_t flags; void * control; @@ -748,6 +744,12 @@ struct _Thread_Control { /** This field is the number of mutexes currently held by this thread. */ uint32_t resource_count; + + /** + * @brief Scheduler related control. + */ + Thread_Scheduler_control Scheduler; + /** This field is the blocking information for this thread. */ Thread_Wait_information Wait; /** This field is the Watchdog used to manage thread delays and timeouts. */ @@ -786,11 +788,6 @@ struct _Thread_Control { /** This field is true if the thread uses the floating point unit. */ bool is_fp; - /** - * @brief Scheduler related control. - */ - Thread_Scheduler_control Scheduler; - #if __RTEMS_ADA__ /** This field is the GNAT self context pointer. */ void *rtems_ada_self; diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 1c043c3..2b45a2e 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -77,12 +77,6 @@ extern Thread_Information _Thread_Internal_information; extern Thread_Control *_Thread_Allocated_fp; #endif -#define THREAD_CHAIN_NODE_TO_THREAD( node ) \ - RTEMS_CONTAINER_OF( node, Thread_Control, Wait.Node.Chain ) - -#define THREAD_RBTREE_NODE_TO_THREAD( node ) \ - RTEMS_CONTAINER_OF( node, Thread_Control, Wait.Node.RBTree ) - #if defined(RTEMS_SMP) #define THREAD_RESOURCE_NODE_TO_THREAD( node ) \ RTEMS_CONTAINER_OF( node, Thread_Control, Resource_node ) diff --git a/cpukit/score/src/thread.c b/cpukit/score/src/thread.c index 8028540..c569ae5 100644 --- a/cpukit/score/src/thread.c +++ b/cpukit/score/src/thread.c @@ -36,6 +36,7 @@ THREAD_OFFSET_ASSERT( current_priority ); THREAD_OFFSET_ASSERT( real_priority ); THREAD_OFFSET_ASSERT( priority_restore_hint ); THREAD_OFFSET_ASSERT( resource_count ); +THREAD_OFFSET_ASSERT( Scheduler ); THREAD_OFFSET_ASSERT( Wait ); THREAD_OFFSET_ASSERT( Timer ); #if defined(RTEMS_MULTIPROCESSING) diff --git a/cpukit/score/src/threadmp.c b/cpukit/score/src/threadmp.c index f525356..cbb6c1c 100644 --- a/cpukit/score/src/threadmp.c +++ b/cpukit/score/src/threadmp.c @@ -20,6 +20,7 @@ #include <rtems/score/threadimpl.h> #include <rtems/score/isrlock.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/wkspace.h> #include <string.h> @@ -74,6 +75,16 @@ void _Thread_MP_Handler_initialization ( _Thread_Timer_initialize( &proxy->Timer, _Per_CPU_Get_by_index( 0 ) ); _RBTree_Initialize_node( &proxy->Active ); +#if defined(RTEMS_SMP) + proxy->Scheduler.own_node = &proxy->Scheduler_node; +#endif + proxy->Scheduler.node = &proxy->Scheduler_node; + _Scheduler_Node_do_initialize( + &proxy->Scheduler_node, + (Thread_Control *) proxy, + 0 + ); + proxy->Wait.spare_heads = &proxy->Thread_queue_heads[ 0 ]; _Thread_queue_Heads_initialize( proxy->Wait.spare_heads ); } diff --git a/cpukit/score/src/threadqflush.c b/cpukit/score/src/threadqflush.c index 835858d..fb13230 100644 --- a/cpukit/score/src/threadqflush.c +++ b/cpukit/score/src/threadqflush.c @@ -19,6 +19,7 @@ #endif #include <rtems/score/threadimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/status.h> Thread_Control *_Thread_queue_Flush_default_filter( @@ -96,7 +97,10 @@ size_t _Thread_queue_Flush_critical( queue_context ); if ( do_unblock ) { - _Chain_Append_unprotected( &unblock, &first->Wait.Node.Chain ); + Scheduler_Node *scheduler_node; + + scheduler_node = _Scheduler_Thread_get_own_node( first ); + _Chain_Append_unprotected( &unblock, &scheduler_node->Wait.Node.Chain ); } ++flushed; @@ -114,11 +118,13 @@ size_t _Thread_queue_Flush_critical( _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context ); do { + Scheduler_Node *scheduler_node; Thread_Control *the_thread; Chain_Node *next; next = _Chain_Next( node ); - the_thread = THREAD_CHAIN_NODE_TO_THREAD( node ); + scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( node ); + the_thread = _Scheduler_Node_get_owner( scheduler_node ); _Thread_Remove_timer_and_unblock( the_thread, queue ); node = next; diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c index 1545f29..b72421e 100644 --- a/cpukit/score/src/threadqops.c +++ b/cpukit/score/src/threadqops.c @@ -99,7 +99,14 @@ static void _Thread_queue_FIFO_do_initialize( Thread_Control *the_thread ) { - _Chain_Initialize_one( &heads->Heads.Fifo, &the_thread->Wait.Node.Chain ); + Scheduler_Node *scheduler_node; + + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); + + _Chain_Initialize_one( + &heads->Heads.Fifo, + &scheduler_node->Wait.Node.Chain + ); } static void _Thread_queue_FIFO_do_enqueue( @@ -107,10 +114,14 @@ static void _Thread_queue_FIFO_do_enqueue( Thread_Control *the_thread ) { - _Chain_Initialize_node( &the_thread->Wait.Node.Chain ); + Scheduler_Node *scheduler_node; + + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); + + _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain ); _Chain_Append_unprotected( &heads->Heads.Fifo, - &the_thread->Wait.Node.Chain + &scheduler_node->Wait.Node.Chain ); } @@ -119,7 +130,10 @@ static void _Thread_queue_FIFO_do_extract( Thread_Control *the_thread ) { - _Chain_Extract_unprotected( &the_thread->Wait.Node.Chain ); + Scheduler_Node *scheduler_node; + + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); + _Chain_Extract_unprotected( &scheduler_node->Wait.Node.Chain ); } static void _Thread_queue_FIFO_enqueue( @@ -155,13 +169,16 @@ static Thread_Control *_Thread_queue_FIFO_first( Thread_queue_Heads *heads ) { - Chain_Control *fifo = &heads->Heads.Fifo; - Chain_Node *first; + Chain_Control *fifo; + Chain_Node *first; + Scheduler_Node *scheduler_node; + fifo = &heads->Heads.Fifo; _Assert( !_Chain_Is_empty( fifo ) ); first = _Chain_First( fifo ); + scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first ); - return THREAD_CHAIN_NODE_TO_THREAD( first ); + return _Scheduler_Node_get_owner( scheduler_node ); } static Thread_Control *_Thread_queue_FIFO_surrender( @@ -205,10 +222,12 @@ static bool _Thread_queue_Priority_less( ) { const Priority_Control *the_left; + const Scheduler_Node *scheduler_node; const Thread_Control *the_right; the_left = left; - the_right = THREAD_RBTREE_NODE_TO_THREAD( right ); + scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( right ); + the_right = _Scheduler_Node_get_owner( scheduler_node ); return *the_left < the_right->current_priority; } @@ -219,20 +238,23 @@ static void _Thread_queue_Priority_priority_change( Priority_Control new_priority ) { - Thread_queue_Heads *heads = queue->heads; + Thread_queue_Heads *heads; Thread_queue_Priority_queue *priority_queue; + Scheduler_Node *scheduler_node; + heads = queue->heads; _Assert( heads != NULL ); priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); _RBTree_Extract( &priority_queue->Queue, - &the_thread->Wait.Node.RBTree + &scheduler_node->Wait.Node.RBTree ); _RBTree_Insert_inline( &priority_queue->Queue, - &the_thread->Wait.Node.RBTree, + &scheduler_node->Wait.Node.RBTree, &new_priority, _Thread_queue_Priority_less ); @@ -244,6 +266,7 @@ static void _Thread_queue_Priority_do_initialize( ) { Thread_queue_Priority_queue *priority_queue; + Scheduler_Node *scheduler_node; priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); @@ -251,9 +274,11 @@ static void _Thread_queue_Priority_do_initialize( _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node ); #endif + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); + _RBTree_Initialize_one( &priority_queue->Queue, - &the_thread->Wait.Node.RBTree + &scheduler_node->Wait.Node.RBTree ); } @@ -263,6 +288,7 @@ static void _Thread_queue_Priority_do_enqueue( ) { Thread_queue_Priority_queue *priority_queue; + Scheduler_Node *scheduler_node; Priority_Control current_priority; priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); @@ -273,11 +299,13 @@ static void _Thread_queue_Priority_do_enqueue( } #endif + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); current_priority = the_thread->current_priority; - _RBTree_Initialize_node( &the_thread->Wait.Node.RBTree ); + + _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree ); _RBTree_Insert_inline( &priority_queue->Queue, - &the_thread->Wait.Node.RBTree, + &scheduler_node->Wait.Node.RBTree, ¤t_priority, _Thread_queue_Priority_less ); @@ -288,12 +316,15 @@ static void _Thread_queue_Priority_do_extract( Thread_Control *the_thread ) { - Thread_queue_Priority_queue *priority_queue = - _Thread_queue_Priority_queue( heads, the_thread ); + Thread_queue_Priority_queue *priority_queue; + Scheduler_Node *scheduler_node; + + priority_queue = _Thread_queue_Priority_queue( heads, the_thread ); + scheduler_node = _Scheduler_Thread_get_own_node( the_thread ); _RBTree_Extract( &priority_queue->Queue, - &the_thread->Wait.Node.RBTree + &scheduler_node->Wait.Node.RBTree ); #if defined(RTEMS_SMP) @@ -340,6 +371,7 @@ static Thread_Control *_Thread_queue_Priority_first( { Thread_queue_Priority_queue *priority_queue; RBTree_Node *first; + Scheduler_Node *scheduler_node; #if defined(RTEMS_SMP) _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) ); @@ -351,8 +383,9 @@ static Thread_Control *_Thread_queue_Priority_first( _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) ); first = _RBTree_Minimum( &priority_queue->Queue ); + scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first ); - return THREAD_RBTREE_NODE_TO_THREAD( first ); + return _Scheduler_Node_get_owner( scheduler_node ); } static Thread_Control *_Thread_queue_Priority_surrender( -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel