summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/schedulersmpimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/include/rtems/score/schedulersmpimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/schedulersmpimpl.h180
1 files changed, 75 insertions, 105 deletions
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 161f742d18..365edbb845 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -37,14 +37,12 @@ extern "C" {
*
* The scheduler nodes can be in four states
* - @ref SCHEDULER_SMP_NODE_BLOCKED,
- * - @ref SCHEDULER_SMP_NODE_SCHEDULED,
- * - @ref SCHEDULER_SMP_NODE_READY, and
- * - @ref SCHEDULER_SMP_NODE_IN_THE_AIR.
+ * - @ref SCHEDULER_SMP_NODE_SCHEDULED, and
+ * - @ref SCHEDULER_SMP_NODE_READY.
*
- * State transitions are triggered via basic three operations
- * - _Scheduler_SMP_Enqueue_ordered(),
- * - _Scheduler_SMP_Extract(), and
- * - _Scheduler_SMP_Schedule().
+ * State transitions are triggered via basic operations
+ * - _Scheduler_SMP_Enqueue_ordered(), and
+ * - _Scheduler_SMP_Block().
*
* @dot
* digraph {
@@ -53,39 +51,26 @@ extern "C" {
* bs [label="BLOCKED"];
* ss [label="SCHEDULED", fillcolor="green"];
* rs [label="READY", fillcolor="red"];
- * as [label="IN THE AIR", fillcolor="orange"];
*
* edge [label="enqueue"];
* edge [fontcolor="darkgreen", color="darkgreen"];
*
* bs -> ss;
- * as -> ss;
*
- * edge [label="enqueue"];
* edge [fontcolor="red", color="red"];
*
* bs -> rs;
- * as -> rs;
*
* edge [label="enqueue other"];
*
* ss -> rs;
*
- * edge [label="schedule"];
- * edge [fontcolor="black", color="black"];
- *
- * as -> bs;
- *
- * edge [label="extract"];
- * edge [fontcolor="brown", color="brown"];
- *
- * ss -> as;
- *
+ * edge [label="block"];
* edge [fontcolor="black", color="black"];
*
* rs -> bs;
*
- * edge [label="enqueue other\nschedule other"];
+ * edge [label="block other"];
* edge [fontcolor="darkgreen", color="darkgreen"];
*
* rs -> ss;
@@ -216,38 +201,7 @@ extern "C" {
* }
* @enddot
*
- * Lets do something with A. This can be a blocking operation or a priority
- * change. For this an extract operation is performed first.
- *
- * @dot
- * digraph {
- * node [style="filled"];
- * edge [dir="none"];
- *
- * subgraph {
- * rank = same;
- *
- * b [label="B (2)", fillcolor="green"];
- * a [label="A (1)", fillcolor="orange"];
- * c [label="C (3)", fillcolor="red"];
- * i [label="I (5)", fillcolor="red"];
- * j [label="J (5)", fillcolor="red"];
- * c -> i -> j;
- * }
- *
- * subgraph {
- * rank = same;
- *
- * p0 [label="PROCESSOR 0", shape="box"];
- * p1 [label="PROCESSOR 1", shape="box"];
- * }
- *
- * b -> p0;
- * a -> p1;
- * }
- * @enddot
- *
- * Lets change the priority of thread A to 4 and enqueue it.
+ * Lets change the priority of thread A to 4.
*
* @dot
* digraph {
@@ -278,8 +232,9 @@ extern "C" {
* }
* @enddot
*
- * Alternatively we can also do a blocking operation with thread A. In this
- * case schedule will be called.
+ * Now perform a blocking operation with thread B. Please note that thread A
+ * migrated now from processor 0 to processor 1 and thread C still executes on
+ * processor 1.
*
* @dot
* digraph {
@@ -289,12 +244,12 @@ extern "C" {
* subgraph {
* rank = same;
*
- * b [label="B (2)", fillcolor="green"];
* c [label="C (3)", fillcolor="green"];
+ * a [label="A (4)", fillcolor="green"];
* i [label="I (5)", fillcolor="red"];
* j [label="J (5)", fillcolor="red"];
- * a [label="A (1)"];
- * b -> c;
+ * b [label="B (2)"];
+ * c -> a;
* i -> j;
* }
*
@@ -305,7 +260,7 @@ extern "C" {
* p1 [label="PROCESSOR 1", shape="box"];
* }
*
- * b -> p0;
+ * a -> p0;
* c -> p1;
* }
* @enddot
@@ -332,6 +287,18 @@ typedef void ( *Scheduler_SMP_Move )(
Thread_Control *thread_to_move
);
+typedef void ( *Scheduler_SMP_Update )(
+ Scheduler_Context *context,
+ Scheduler_Node *node,
+ Priority_Control new_priority
+);
+
+typedef void ( *Scheduler_SMP_Enqueue )(
+ Scheduler_Context *context,
+ Thread_Control *thread_to_enqueue,
+ bool has_processor_allocated
+);
+
static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self(
Scheduler_Context *context
)
@@ -360,7 +327,7 @@ static inline void _Scheduler_SMP_Node_initialize(
node->state = SCHEDULER_SMP_NODE_BLOCKED;
}
-extern const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ];
+extern const bool _Scheduler_SMP_Node_valid_state_changes[ 3 ][ 3 ];
static inline void _Scheduler_SMP_Node_change_state(
Scheduler_SMP_Node *node,
@@ -467,6 +434,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
*
* @param[in] context The scheduler instance context.
* @param[in] thread The thread to enqueue.
+ * @param[in] has_processor_allocated The thread has a processor allocated.
* @param[in] order The order function.
* @param[in] get_highest_ready Function to get the highest ready node.
* @param[in] insert_ready Function to insert a node into the set of ready
@@ -481,6 +449,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled(
static inline void _Scheduler_SMP_Enqueue_ordered(
Scheduler_Context *context,
Thread_Control *thread,
+ bool has_processor_allocated,
Chain_Node_order order,
Scheduler_SMP_Get_highest_ready get_highest_ready,
Scheduler_SMP_Insert insert_ready,
@@ -492,19 +461,18 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context );
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
- if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) {
+ if ( has_processor_allocated) {
Thread_Control *highest_ready = ( *get_highest_ready )( &self->Base );
+ _Assert( highest_ready != NULL);
+
/*
* The thread has been extracted from the scheduled chain. We have to
* place it now on the scheduled or ready chain.
*
* NOTE: Do not exchange parameters to do the negation of the order check.
*/
- if (
- highest_ready != NULL
- && !( *order )( &thread->Object.Node, &highest_ready->Object.Node )
- ) {
+ if ( !( *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->Base, thread );
@@ -517,14 +485,9 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
Thread_Control *lowest_scheduled =
_Scheduler_SMP_Get_lowest_scheduled( self );
- /*
- * The scheduled chain is empty if nested interrupts change the priority of
- * all scheduled threads. These threads are in the air.
- */
- if (
- lowest_scheduled != NULL
- && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node )
- ) {
+ _Assert( lowest_scheduled != NULL);
+
+ if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) {
Scheduler_SMP_Node *lowest_scheduled_node =
_Scheduler_SMP_Node_get( lowest_scheduled );
@@ -542,6 +505,11 @@ static inline void _Scheduler_SMP_Enqueue_ordered(
}
}
+static inline void _Scheduler_SMP_Extract_from_scheduled( Thread_Control *thread )
+{
+ _Chain_Extract_unprotected( &thread->Object.Node );
+}
+
static inline void _Scheduler_SMP_Schedule_highest_ready(
Scheduler_Context *context,
Thread_Control *victim,
@@ -558,25 +526,31 @@ static inline void _Scheduler_SMP_Schedule_highest_ready(
}
/**
- * @brief Finalize a scheduling operation.
+ * @brief Blocks a thread.
*
* @param[in] context The scheduler instance context.
* @param[in] thread The thread of the scheduling operation.
+ * @param[in] extract_from_ready Function to extract a node from the set of
+ * ready nodes.
* @param[in] get_highest_ready Function to get the highest ready node.
* @param[in] move_from_ready_to_scheduled Function to move a node from the set
* of ready nodes to the set of scheduled nodes.
*/
-static inline void _Scheduler_SMP_Schedule(
+static inline void _Scheduler_SMP_Block(
Scheduler_Context *context,
Thread_Control *thread,
+ Scheduler_SMP_Extract extract_from_ready,
Scheduler_SMP_Get_highest_ready get_highest_ready,
Scheduler_SMP_Move move_from_ready_to_scheduled
)
{
Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
+ bool is_scheduled = node->state == SCHEDULER_SMP_NODE_SCHEDULED;
+
+ _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
- if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) {
- _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED );
+ if ( is_scheduled ) {
+ _Scheduler_SMP_Extract_from_scheduled( thread );
_Scheduler_SMP_Schedule_highest_ready(
context,
@@ -584,42 +558,38 @@ static inline void _Scheduler_SMP_Schedule(
get_highest_ready,
move_from_ready_to_scheduled
);
+ } else {
+ ( *extract_from_ready )( context, thread );
}
}
-static inline void _Scheduler_SMP_Block(
+static inline void _Scheduler_SMP_Change_priority(
Scheduler_Context *context,
Thread_Control *thread,
- Scheduler_SMP_Extract extract,
- Scheduler_SMP_Get_highest_ready get_highest_ready,
- Scheduler_SMP_Move move_from_ready_to_scheduled
+ Priority_Control new_priority,
+ bool prepend_it,
+ Scheduler_SMP_Extract extract_from_ready,
+ Scheduler_SMP_Update update,
+ Scheduler_SMP_Enqueue enqueue_fifo,
+ Scheduler_SMP_Enqueue enqueue_lifo
)
{
- ( *extract )( context, thread );
+ Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread );
+ bool has_processor_allocated = node->state == SCHEDULER_SMP_NODE_SCHEDULED;
- _Scheduler_SMP_Schedule(
- context,
- thread,
- get_highest_ready,
- move_from_ready_to_scheduled
- );
-}
+ if ( has_processor_allocated ) {
+ _Scheduler_SMP_Extract_from_scheduled( thread );
+ } else {
+ ( *extract_from_ready )( context, thread );
+ }
-/**
- * @brief Extracts a thread from the set of scheduled or ready nodes.
- *
- * @param[in] context The scheduler instance context.
- * @param[in] thread The thread to extract.
- * @param[in] extract Function to extract a node from the set of scheduled or
- * ready nodes.
- */
-static inline void _Scheduler_SMP_Extract(
- Scheduler_Context *context,
- Thread_Control *thread,
- Scheduler_SMP_Extract extract
-)
-{
- ( *extract )( context, thread );
+ ( *update )( context, &node->Base, new_priority );
+
+ if ( prepend_it ) {
+ ( *enqueue_lifo )( context, thread, has_processor_allocated );
+ } else {
+ ( *enqueue_fifo )( context, thread, has_processor_allocated );
+ }
}
static inline void _Scheduler_SMP_Insert_scheduled_lifo(