Add the ability to add/remove scheduler nodes to/from the set of scheduler nodes available to the schedulers for a particular thread.
Update #2556. --- cpukit/score/include/rtems/score/schedulerimpl.h | 8 +++ cpukit/score/include/rtems/score/schedulernode.h | 62 +++++++++++++++++++++++- cpukit/score/include/rtems/score/thread.h | 15 ++++++ cpukit/score/include/rtems/score/threadimpl.h | 47 +++++++++++++++++- cpukit/score/src/threadinitialize.c | 4 ++ 5 files changed, 133 insertions(+), 3 deletions(-) diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 6d2f5a1..26da986 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -1471,6 +1471,14 @@ RTEMS_INLINE_ROUTINE Status_Control _Scheduler_Set( &the_thread->Scheduler.Wait_nodes, &new_scheduler_node->Thread.Wait_node ); + _Chain_Extract_unprotected( + &old_scheduler_node->Thread.Scheduler_node.Chain + ); + _Assert( _Chain_Is_empty( &the_thread->Scheduler.Scheduler_nodes ) ); + _Chain_Initialize_one( + &the_thread->Scheduler.Scheduler_nodes, + &new_scheduler_node->Thread.Scheduler_node.Chain + ); { const Scheduler_Control *old_scheduler; diff --git a/cpukit/score/include/rtems/score/schedulernode.h b/cpukit/score/include/rtems/score/schedulernode.h index 2397ba4..2e0c2af 100644 --- a/cpukit/score/include/rtems/score/schedulernode.h +++ b/cpukit/score/include/rtems/score/schedulernode.h @@ -95,10 +95,43 @@ typedef enum { } Scheduler_Help_state; #endif +#if defined(RTEMS_SMP) +/** + * @brief The scheduler node requests. + */ +typedef enum { + /** + * @brief The scheduler node is not on the list of pending requests. + */ + SCHEDULER_NODE_REQUEST_NOT_PENDING, + + /** + * @brief There is a pending scheduler node request to add this scheduler + * node to the Thread_Control::Scheduler::Scheduler_nodes chain. + */ + SCHEDULER_NODE_REQUEST_ADD, + + /** + * @brief There is a pending scheduler node request to remove this scheduler + * node from the Thread_Control::Scheduler::Scheduler_nodes chain. + */ + SCHEDULER_NODE_REQUEST_REMOVE, + + /** + * @brief The scheduler node is on the list of pending requests, but nothing + * should change. + */ + SCHEDULER_NODE_REQUEST_NOTHING, + +} Scheduler_Node_request; +#endif + +typedef struct Scheduler_Node Scheduler_Node; + /** * @brief Scheduler node for per-thread data. */ -typedef struct Scheduler_Node { +struct Scheduler_Node { #if defined(RTEMS_SMP) /** * @brief Chain node for usage in various scheduler data structures. @@ -149,6 +182,28 @@ typedef struct Scheduler_Node { * Thread_Control::Scheduler::Wait_nodes. */ Chain_Node Wait_node; + + /** + * @brief Node to add this scheduler node to + * Thread_Control::Scheduler::Scheduler_nodes. + */ + union { + /** + * @brief The node for Thread_Control::Scheduler::Scheduler_nodes. + */ + Chain_Node Chain; + } Scheduler_node; + + /** + * @brief Link to the next scheduler node in the + * Thread_Control::Scheduler::requests list. + */ + Scheduler_Node *next_request; + + /** + * @brief The current scheduler node request. + */ + Scheduler_Node_request request; } Thread; #endif @@ -198,7 +253,7 @@ typedef struct Scheduler_Node { */ bool prepend_it; } Priority; -} Scheduler_Node; +}; #if defined(RTEMS_SMP) /** @@ -212,6 +267,9 @@ extern const size_t _Scheduler_Node_size; #if defined(RTEMS_SMP) #define SCHEDULER_NODE_OF_THREAD_WAIT_NODE( node ) \ RTEMS_CONTAINER_OF( node, Scheduler_Node, Thread.Wait_node ) + +#define SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node ) \ + RTEMS_CONTAINER_OF( node, Scheduler_Node, Thread.Scheduler_node.Chain ) #endif #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index e9f3465..8595ed0 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -300,6 +300,21 @@ typedef struct { * This chain is protected by the thread wait lock. */ Chain_Control Wait_nodes; + + /** + * @brief Scheduler nodes immediately available to the schedulers for this + * thread. + * + * This chain is protected by the thread state lock. + */ + Chain_Control Scheduler_nodes; + + /** + * @brief List of pending scheduler node requests. + * + * This list is protected by the thread scheduler lock. + */ + Scheduler_Node *requests; #endif /** diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index b7e1b87..6f2037f 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -1044,6 +1044,42 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_release_critical( _ISR_lock_Release( &the_thread->Scheduler.Lock, lock_context ); } +RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_request( + Thread_Control *the_thread, + Scheduler_Node *scheduler_node, + Scheduler_Node_request request +) +{ + ISR_lock_Context lock_context; + Scheduler_Node_request current_request; + + _Thread_Scheduler_acquire_critical( the_thread, &lock_context ); + + current_request = scheduler_node->Thread.request; + + if ( current_request == SCHEDULER_NODE_REQUEST_NOT_PENDING ) { + _Assert( + request == SCHEDULER_NODE_REQUEST_ADD + || request == SCHEDULER_NODE_REQUEST_REMOVE + ); + _Assert( scheduler_node->Thread.next_request == NULL ); + scheduler_node->Thread.next_request = the_thread->Scheduler.requests; + the_thread->Scheduler.requests = scheduler_node; + } else if ( current_request != SCHEDULER_NODE_REQUEST_NOTHING ) { + _Assert( + ( current_request == SCHEDULER_NODE_REQUEST_ADD + && request == SCHEDULER_NODE_REQUEST_REMOVE ) + || ( current_request == SCHEDULER_NODE_REQUEST_REMOVE + && request == SCHEDULER_NODE_REQUEST_ADD ) + ); + request = SCHEDULER_NODE_REQUEST_NOTHING; + } + + scheduler_node->Thread.request = request; + + _Thread_Scheduler_release_critical( the_thread, &lock_context ); +} + RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_wait_node( Thread_Control *the_thread, Scheduler_Node *scheduler_node @@ -1053,6 +1089,11 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_add_wait_node( &the_thread->Scheduler.Wait_nodes, &scheduler_node->Thread.Wait_node ); + _Thread_Scheduler_add_request( + the_thread, + scheduler_node, + SCHEDULER_NODE_REQUEST_ADD + ); } RTEMS_INLINE_ROUTINE void _Thread_Scheduler_remove_wait_node( @@ -1060,8 +1101,12 @@ RTEMS_INLINE_ROUTINE void _Thread_Scheduler_remove_wait_node( Scheduler_Node *scheduler_node ) { - (void) the_thread; _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node ); + _Thread_Scheduler_add_request( + the_thread, + scheduler_node, + SCHEDULER_NODE_REQUEST_REMOVE + ); } #endif diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index 62c3066..8fe1785 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -210,6 +210,10 @@ bool _Thread_Initialize( &the_thread->Scheduler.Wait_nodes, &scheduler_node->Thread.Wait_node ); + _Chain_Initialize_one( + &the_thread->Scheduler.Scheduler_nodes, + &scheduler_node->Thread.Scheduler_node.Chain + ); #else scheduler_node = _Thread_Scheduler_get_own_node( the_thread ); _Scheduler_Node_initialize( -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel