score: Add scheduler node requests

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.
This commit is contained in:
Sebastian Huber
2016-09-23 13:24:06 +02:00
parent edb020ca67
commit ebdd2a3431
5 changed files with 133 additions and 3 deletions

View File

@@ -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;

View File

@@ -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

View File

@@ -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
/**

View File

@@ -1051,6 +1051,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
@@ -1060,6 +1096,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(
@@ -1067,8 +1108,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

View File

@@ -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(