summaryrefslogtreecommitdiffstats
path: root/cpukit/score/src/threadqops.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/src/threadqops.c')
-rw-r--r--cpukit/score/src/threadqops.c847
1 files changed, 661 insertions, 186 deletions
diff --git a/cpukit/score/src/threadqops.c b/cpukit/score/src/threadqops.c
index e20241d494..602d6bbffb 100644
--- a/cpukit/score/src/threadqops.c
+++ b/cpukit/score/src/threadqops.c
@@ -22,31 +22,58 @@
#include <rtems/score/rbtreeimpl.h>
#include <rtems/score/schedulerimpl.h>
-static void _Thread_queue_Do_nothing_priority_change(
+#define THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ) \
+ RTEMS_CONTAINER_OF( \
+ priority_actions, \
+ Thread_queue_Context, \
+ Priority.Actions \
+ )
+
+#define THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION( \
+ priority_aggregation \
+) \
+ RTEMS_CONTAINER_OF( \
+ priority_aggregation, \
+ Thread_queue_Priority_queue, \
+ Queue \
+ )
+
+static void _Thread_queue_Do_nothing_priority_actions(
Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Priority_Control new_priority
+ Priority_Actions *priority_actions
)
{
(void) queue;
- (void) the_thread;
- (void) new_priority;
+ _Priority_Actions_initialize_empty( priority_actions );
}
static void _Thread_queue_Do_nothing_extract(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
(void) queue;
(void) the_thread;
+ (void) queue_context;
}
-static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- void ( *initialize )( Thread_queue_Heads *, Thread_Control * ),
- void ( *enqueue )( Thread_queue_Heads *, Thread_Control * )
+static void _Thread_queue_Queue_enqueue(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ void ( *initialize )(
+ Thread_queue_Queue *,
+ Thread_Control *,
+ Thread_queue_Context *,
+ Thread_queue_Heads *
+ ),
+ void ( *enqueue )(
+ Thread_queue_Queue *,
+ Thread_Control *,
+ Thread_queue_Context *,
+ Thread_queue_Heads *
+ )
)
{
Thread_queue_Heads *heads;
@@ -63,20 +90,26 @@ static Thread_queue_Heads *_Thread_queue_Queue_enqueue(
heads = spare_heads;
queue->heads = heads;
_Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
- ( *initialize )( heads, the_thread );
+ ( *initialize )( queue, the_thread, queue_context, heads );
} else {
_Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
- ( *enqueue )( heads, the_thread );
+ ( *enqueue )( queue, the_thread, queue_context, heads );
}
-
- return heads;
}
static void _Thread_queue_Queue_extract(
- Thread_queue_Queue *queue,
- Thread_queue_Heads *heads,
- Thread_Control *the_thread,
- void ( *extract )( Thread_queue_Heads *, Thread_Control * )
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *current_or_previous_owner,
+ Thread_queue_Context *queue_context,
+ Thread_Control *the_thread,
+ void ( *extract )(
+ Thread_queue_Queue *,
+ Thread_queue_Heads *,
+ Thread_Control *,
+ Thread_queue_Context *,
+ Thread_Control *
+ )
)
{
_Assert( heads != NULL );
@@ -91,76 +124,95 @@ static void _Thread_queue_Queue_extract(
queue->heads = NULL;
}
- ( *extract )( heads, the_thread );
+ ( *extract )(
+ queue,
+ heads,
+ current_or_previous_owner,
+ queue_context,
+ the_thread
+ );
}
static void _Thread_queue_FIFO_do_initialize(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
)
{
Scheduler_Node *scheduler_node;
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
- _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
+ _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
_Chain_Initialize_one(
&heads->Heads.Fifo,
- &scheduler_node->Wait.Node.Chain
+ &scheduler_node->Wait.Priority.Node.Node.Chain
);
}
static void _Thread_queue_FIFO_do_enqueue(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
)
{
Scheduler_Node *scheduler_node;
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
- _Chain_Initialize_node( &scheduler_node->Wait.Node.Chain );
+ _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
_Chain_Append_unprotected(
&heads->Heads.Fifo,
- &scheduler_node->Wait.Node.Chain
+ &scheduler_node->Wait.Priority.Node.Node.Chain
);
}
static void _Thread_queue_FIFO_do_extract(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *current_or_previous_owner,
+ Thread_queue_Context *queue_context,
+ Thread_Control *the_thread
)
{
Scheduler_Node *scheduler_node;
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
- _Chain_Extract_unprotected( &scheduler_node->Wait.Node.Chain );
+ (void) current_or_previous_owner;
+ (void) queue_context;
+
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+
+ _Chain_Extract_unprotected( &scheduler_node->Wait.Priority.Node.Node.Chain );
}
static void _Thread_queue_FIFO_enqueue(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Thread_queue_Path *path
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
- path->update_priority = NULL;
-
_Thread_queue_Queue_enqueue(
queue,
the_thread,
+ queue_context,
_Thread_queue_FIFO_do_initialize,
_Thread_queue_FIFO_do_enqueue
);
}
static void _Thread_queue_FIFO_extract(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
_Thread_queue_Queue_extract(
queue,
queue->heads,
+ NULL,
+ queue_context,
the_thread,
_Thread_queue_FIFO_do_extract
);
@@ -177,15 +229,16 @@ static Thread_Control *_Thread_queue_FIFO_first(
fifo = &heads->Heads.Fifo;
_Assert( !_Chain_Is_empty( fifo ) );
first = _Chain_First( fifo );
- scheduler_node = SCHEDULER_NODE_OF_WAIT_CHAIN_NODE( first );
+ scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
return _Scheduler_Node_get_owner( scheduler_node );
}
static Thread_Control *_Thread_queue_FIFO_surrender(
- Thread_queue_Queue *queue,
- Thread_queue_Heads *heads,
- Thread_Control *previous_owner
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *previous_owner,
+ Thread_queue_Context *queue_context
)
{
Thread_Control *first;
@@ -194,6 +247,8 @@ static Thread_Control *_Thread_queue_FIFO_surrender(
_Thread_queue_Queue_extract(
queue,
heads,
+ NULL,
+ queue_context,
first,
_Thread_queue_FIFO_do_extract
);
@@ -203,165 +258,162 @@ static Thread_Control *_Thread_queue_FIFO_surrender(
static Thread_queue_Priority_queue *_Thread_queue_Priority_queue(
Thread_queue_Heads *heads,
- const Thread_Control *the_thread
+ const Scheduler_Node *scheduler_node
)
{
#if defined(RTEMS_SMP)
- return &heads->Priority[
- _Scheduler_Get_index( _Scheduler_Get_own( the_thread ) )
- ];
-#else
- (void) the_thread;
+ const Scheduler_Control *scheduler;
+ scheduler = _Priority_Get_scheduler( &scheduler_node->Wait.Priority );
+ return &heads->Priority[ _Scheduler_Get_index( scheduler ) ];
+#else
+ (void) scheduler_node;
return &heads->Heads.Priority;
#endif
}
-static bool _Thread_queue_Priority_less(
- const void *left,
- const RBTree_Node *right
-)
-{
- const Priority_Control *the_left;
- const Scheduler_Node *scheduler_node;
- const Thread_Control *the_right;
-
- the_left = left;
- scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( right );
- the_right = _Scheduler_Node_get_owner( scheduler_node );
-
- return *the_left < _Thread_Get_priority( the_right );
-}
-
-static void _Thread_queue_Priority_priority_change(
+static void _Thread_queue_Priority_priority_actions(
Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Priority_Control new_priority
+ Priority_Actions *priority_actions
)
{
- Thread_queue_Heads *heads;
- Thread_queue_Priority_queue *priority_queue;
- Scheduler_Node *scheduler_node;
+ Thread_queue_Heads *heads;
+ Priority_Aggregation *priority_aggregation;
heads = queue->heads;
_Assert( heads != NULL );
- priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+ _Assert( !_Priority_Actions_is_empty( priority_actions ) );
+ priority_aggregation = _Priority_Actions_move( priority_actions );
- _RBTree_Extract(
- &priority_queue->Queue,
- &scheduler_node->Wait.Node.RBTree
- );
- _RBTree_Insert_inline(
- &priority_queue->Queue,
- &scheduler_node->Wait.Node.RBTree,
- &new_priority,
- _Thread_queue_Priority_less
- );
+ do {
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+
+ scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
+
+ _Assert( priority_aggregation->Action.type == PRIORITY_ACTION_CHANGE );
+ _Priority_Plain_changed(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node
+ );
+
+ priority_aggregation = _Priority_Get_next_action( priority_aggregation );
+ } while ( _Priority_Actions_is_valid( priority_aggregation ) );
}
static void _Thread_queue_Priority_do_initialize(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
)
{
- Thread_queue_Priority_queue *priority_queue;
Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
- priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
#if defined(RTEMS_SMP)
_Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
#endif
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
-
- _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
- _RBTree_Initialize_one(
+ _Priority_Initialize_one(
&priority_queue->Queue,
- &scheduler_node->Wait.Node.RBTree
+ &scheduler_node->Wait.Priority.Node
);
}
static void _Thread_queue_Priority_do_enqueue(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
)
{
- Thread_queue_Priority_queue *priority_queue;
Scheduler_Node *scheduler_node;
- Priority_Control current_priority;
+ Thread_queue_Priority_queue *priority_queue;
- priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
#if defined(RTEMS_SMP)
- if ( _RBTree_Is_empty( &priority_queue->Queue ) ) {
+ if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
_Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+ _Priority_Initialize_one(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node
+ );
+ return;
}
#endif
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
- current_priority = _Thread_Get_priority( the_thread );
-
- _RBTree_Initialize_node( &scheduler_node->Wait.Node.RBTree );
- _RBTree_Insert_inline(
+ _Priority_Plain_insert(
&priority_queue->Queue,
- &scheduler_node->Wait.Node.RBTree,
- &current_priority,
- _Thread_queue_Priority_less
+ &scheduler_node->Wait.Priority.Node,
+ _Priority_Get_priority( &scheduler_node->Wait.Priority )
);
}
static void _Thread_queue_Priority_do_extract(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *current_or_previous_owner,
+ Thread_queue_Context *queue_context,
+ Thread_Control *the_thread
)
{
- Thread_queue_Priority_queue *priority_queue;
Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+
+ (void) current_or_previous_owner;
+ (void) queue_context;
- priority_queue = _Thread_queue_Priority_queue( heads, the_thread );
- scheduler_node = _Scheduler_Thread_get_own_node( the_thread );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
- _RBTree_Extract(
+ _Priority_Plain_extract(
&priority_queue->Queue,
- &scheduler_node->Wait.Node.RBTree
+ &scheduler_node->Wait.Priority.Node
);
#if defined(RTEMS_SMP)
_Chain_Extract_unprotected( &priority_queue->Node );
- if ( !_RBTree_Is_empty( &priority_queue->Queue ) ) {
+ if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
_Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
}
#endif
}
static void _Thread_queue_Priority_enqueue(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Thread_queue_Path *path
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
- path->update_priority = NULL;
-
_Thread_queue_Queue_enqueue(
queue,
the_thread,
+ queue_context,
_Thread_queue_Priority_do_initialize,
_Thread_queue_Priority_do_enqueue
);
}
static void _Thread_queue_Priority_extract(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
)
{
_Thread_queue_Queue_extract(
queue,
queue->heads,
+ NULL,
+ queue_context,
the_thread,
_Thread_queue_Priority_do_extract
);
@@ -372,7 +424,7 @@ static Thread_Control *_Thread_queue_Priority_first(
)
{
Thread_queue_Priority_queue *priority_queue;
- RBTree_Node *first;
+ Priority_Node *first;
Scheduler_Node *scheduler_node;
#if defined(RTEMS_SMP)
@@ -383,17 +435,18 @@ static Thread_Control *_Thread_queue_Priority_first(
priority_queue = &heads->Heads.Priority;
#endif
- _Assert( !_RBTree_Is_empty( &priority_queue->Queue ) );
- first = _RBTree_Minimum( &priority_queue->Queue );
- scheduler_node = SCHEDULER_NODE_OF_WAIT_RBTREE_NODE( first );
+ _Assert( !_Priority_Is_empty( &priority_queue->Queue ) );
+ first = _Priority_Get_minimum_node( &priority_queue->Queue );
+ scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
return _Scheduler_Node_get_owner( scheduler_node );
}
static Thread_Control *_Thread_queue_Priority_surrender(
- Thread_queue_Queue *queue,
- Thread_queue_Heads *heads,
- Thread_Control *previous_owner
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *previous_owner,
+ Thread_queue_Context *queue_context
)
{
Thread_Control *first;
@@ -402,6 +455,8 @@ static Thread_Control *_Thread_queue_Priority_surrender(
_Thread_queue_Queue_extract(
queue,
heads,
+ NULL,
+ queue_context,
first,
_Thread_queue_Priority_do_extract
);
@@ -409,104 +464,524 @@ static Thread_Control *_Thread_queue_Priority_surrender(
return first;
}
-static void _Thread_queue_Priority_inherit_enqueue(
- Thread_queue_Queue *queue,
- Thread_Control *the_thread,
- Thread_queue_Path *path
+static void _Thread_queue_Priority_inherit_do_actions_change(
+ Priority_Aggregation *priority_aggregation,
+ bool prepend_it,
+ Priority_Actions *priority_actions,
+ void *arg
)
{
- Thread_queue_Heads *heads;
- Thread_Control *owner;
- Priority_Control priority;
+ Thread_queue_Priority_queue *priority_queue;
+ Scheduler_Node *scheduler_node;
- heads = _Thread_queue_Queue_enqueue(
- queue,
- the_thread,
- _Thread_queue_Priority_do_initialize,
- _Thread_queue_Priority_do_enqueue
+ priority_queue = THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION(
+ priority_aggregation
);
+ scheduler_node = priority_queue->scheduler_node;
- owner = queue->owner;
+ _Priority_Set_action(
+ &scheduler_node->Wait.Priority,
+ &priority_aggregation->Node,
+ PRIORITY_ACTION_CHANGE
+ );
+ _Priority_Actions_add( priority_actions, &scheduler_node->Wait.Priority );
+}
-#if defined(RTEMS_SMP)
- if ( _Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
- priority = the_thread->current_priority;
- } else {
- priority = _Scheduler_Map_priority(
- _Scheduler_Get_own( the_thread ),
- PRIORITY_PSEUDO_ISR
+static void _Thread_queue_Priority_inherit_priority_actions(
+ Thread_queue_Queue *queue,
+ Priority_Actions *priority_actions
+)
+{
+ Thread_queue_Heads *heads;
+ Priority_Aggregation *priority_aggregation;
+
+ heads = queue->heads;
+ _Assert( heads != NULL );
+
+ _Assert( !_Priority_Actions_is_empty( priority_actions ) );
+ priority_aggregation = _Priority_Actions_move( priority_actions );
+
+ do {
+ Priority_Aggregation *next_aggregation;
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+
+ next_aggregation = _Priority_Get_next_action( priority_aggregation );
+
+ scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
+
+ _Assert( priority_aggregation->Action.type == PRIORITY_ACTION_CHANGE );
+ _Priority_Changed(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node,
+ false,
+ priority_actions,
+ _Thread_queue_Priority_inherit_do_actions_change,
+ NULL
);
+
+ priority_aggregation = next_aggregation;
+ } while ( _Priority_Actions_is_valid( priority_aggregation ) );
+}
+
+static void _Thread_queue_Boost_priority(
+ Thread_queue_Heads *heads,
+ Thread_Control *the_thread,
+ Thread_Control *owner,
+ Thread_queue_Context *queue_context
+)
+{
+#if defined(RTEMS_SMP)
+ const Scheduler_Control *scheduler;
+ const Scheduler_Control *scheduler_of_owner;
+ Scheduler_Node *scheduler_node_of_owner;
+ Priority_Control boost_priority;
+
+ if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
+ return;
}
+
+ scheduler = _Scheduler_Get_own( the_thread );
+ scheduler_of_owner = _Scheduler_Get_own( owner );
+
+ if ( scheduler == scheduler_of_owner ) {
+ return;
+ }
+
+ scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+
+ boost_priority = _Scheduler_Map_priority(
+ scheduler_of_owner,
+ PRIORITY_PSEUDO_ISR
+ );
+
+ _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
+ _Priority_Actions_initialize_one(
+ &queue_context->Priority.Actions,
+ &scheduler_node_of_owner->Wait.Priority,
+ &heads->Boost_priority,
+ PRIORITY_ACTION_ADD
+ );
+ _Thread_Priority_perform_actions( owner, queue_context );
#else
(void) heads;
+ (void) the_thread;
+ (void) owner;
+ (void) queue_context;
+#endif
+}
+
+static void _Thread_queue_Priority_inherit_do_initialize(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
+)
+{
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+ Thread_Control *owner;
+ Scheduler_Node *scheduler_node_of_owner;
+
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
- priority = the_thread->current_priority;
+#if defined(RTEMS_SMP)
+ _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
#endif
- if ( priority < owner->current_priority ) {
- path->update_priority = owner;
+ _Priority_Initialize_one(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node
+ );
- owner->priority_restore_hint = true;
- _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+ owner = queue->owner;
+ scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+ priority_queue->scheduler_node = scheduler_node_of_owner;
+
+ _Priority_Actions_initialize_one(
+ &queue_context->Priority.Actions,
+ &scheduler_node_of_owner->Wait.Priority,
+ &priority_queue->Queue.Node,
+ PRIORITY_ACTION_ADD
+ );
+ _Thread_Priority_perform_actions( owner, queue_context );
+ _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
+}
+
+static void _Thread_queue_Priority_inherit_do_enqueue_change(
+ Priority_Aggregation *priority_aggregation,
+ bool prepend_it,
+ Priority_Actions *priority_actions,
+ void *arg
+)
+{
+ Thread_queue_Queue *queue;
+ Thread_Control *owner;
+ Scheduler_Node *scheduler_node_of_owner;
+ Thread_queue_Context *queue_context;
+
+ queue = arg;
+ owner = queue->owner;
+ scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+ queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
+
+ _Priority_Actions_initialize_one(
+ &queue_context->Priority.Actions,
+ &scheduler_node_of_owner->Wait.Priority,
+ &priority_aggregation->Node,
+ PRIORITY_ACTION_CHANGE
+ );
+ _Thread_Priority_perform_actions( owner, queue_context );
+}
+
+static void _Thread_queue_Priority_inherit_do_enqueue(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context,
+ Thread_queue_Heads *heads
+)
+{
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
- _Scheduler_Thread_set_priority( owner, priority, false );
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
- ( *owner->Wait.operations->priority_change )(
- owner->Wait.queue,
+#if defined(RTEMS_SMP)
+ if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
+ Thread_Control *owner;
+ Scheduler_Node *scheduler_node_of_owner;
+
+ _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+ _Priority_Initialize_one(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node
+ );
+
+ owner = queue->owner;
+ scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+ priority_queue->scheduler_node = scheduler_node_of_owner;
+
+ _Priority_Actions_initialize_one(
+ &queue_context->Priority.Actions,
+ &scheduler_node_of_owner->Wait.Priority,
+ &priority_queue->Queue.Node,
+ PRIORITY_ACTION_ADD
+ );
+ _Thread_Priority_perform_actions( owner, queue_context );
+ _Thread_queue_Boost_priority( heads, the_thread, owner, queue_context );
+ return;
+ }
+#endif
+
+ _Priority_Non_empty_insert(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node,
+ &queue_context->Priority.Actions,
+ _Thread_queue_Priority_inherit_do_enqueue_change,
+ queue
+ );
+ _Thread_queue_Boost_priority(
+ heads,
+ the_thread,
+ queue->owner,
+ queue_context
+ );
+}
+
+static void _Thread_queue_Priority_inherit_enqueue(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
+)
+{
+ _Thread_queue_Queue_enqueue(
+ queue,
+ the_thread,
+ queue_context,
+ _Thread_queue_Priority_inherit_do_initialize,
+ _Thread_queue_Priority_inherit_do_enqueue
+ );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract_action(
+ Priority_Actions *priority_actions,
+ Thread_Control *owner,
+ Priority_Node *priority_action_node,
+ Priority_Action_type priority_action_type
+)
+{
+ Thread_queue_Context *queue_context;
+ Scheduler_Node *scheduler_node_of_owner;
+
+ queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
+ scheduler_node_of_owner = _Thread_Scheduler_get_own_node( owner );
+
+ _Priority_Actions_initialize_one(
+ &queue_context->Priority.Actions,
+ &scheduler_node_of_owner->Wait.Priority,
+ priority_action_node,
+ priority_action_type
+ );
+ _Thread_Priority_perform_actions( owner, queue_context );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract_remove(
+ Priority_Aggregation *priority_aggregation,
+ Priority_Actions *priority_actions,
+ void *arg
+)
+{
+ _Thread_queue_Priority_inherit_do_extract_action(
+ priority_actions,
+ arg,
+ &priority_aggregation->Node,
+ PRIORITY_ACTION_REMOVE
+ );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract_change(
+ Priority_Aggregation *priority_aggregation,
+ bool prepend_it,
+ Priority_Actions *priority_actions,
+ void *arg
+)
+{
+ _Thread_queue_Priority_inherit_do_extract_action(
+ priority_actions,
+ arg,
+ &priority_aggregation->Node,
+ PRIORITY_ACTION_CHANGE
+ );
+}
+
+static void _Thread_queue_Priority_inherit_do_extract(
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *owner,
+ Thread_queue_Context *queue_context,
+ Thread_Control *the_thread
+)
+{
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
+
+ _Thread_queue_Path_acquire_critical( queue, the_thread, queue_context );
+
+ _Priority_Extract(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node,
+ &queue_context->Priority.Actions,
+ _Thread_queue_Priority_inherit_do_extract_remove,
+ _Thread_queue_Priority_inherit_do_extract_change,
+ owner
+ );
+
+#if defined(RTEMS_SMP)
+ _Chain_Extract_unprotected( &priority_queue->Node );
+
+ if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+ _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+ }
+
+ if (
+ _Priority_Node_is_active( &heads->Boost_priority )
+ && ( _Chain_Is_empty( &heads->Heads.Fifo )
+ || _Chain_Has_only_one_node( &heads->Heads.Fifo ) )
+ ) {
+ _Thread_queue_Priority_inherit_do_extract_action(
+ &queue_context->Priority.Actions,
owner,
- priority
+ &heads->Boost_priority,
+ PRIORITY_ACTION_REMOVE
);
- } else {
- path->update_priority = NULL;
+ _Priority_Node_set_inactive( &heads->Boost_priority );
}
+#endif
+
+ _Thread_queue_Path_release_critical( queue_context );
}
-static void _Thread_queue_Boost_priority(
- Thread_queue_Heads *heads,
- Thread_Control *the_thread
+static void _Thread_queue_Priority_inherit_extract(
+ Thread_queue_Queue *queue,
+ Thread_Control *the_thread,
+ Thread_queue_Context *queue_context
+)
+{
+ _Thread_queue_Queue_extract(
+ queue,
+ queue->heads,
+ queue->owner,
+ queue_context,
+ the_thread,
+ _Thread_queue_Priority_inherit_do_extract
+ );
+}
+
+static void _Thread_queue_Priority_inherit_do_surrender_change(
+ Priority_Aggregation *priority_aggregation,
+ bool prepend_it,
+ Priority_Actions *priority_actions,
+ void *arg
)
{
+ _Thread_queue_Context_add_priority_update(
+ THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ),
+ arg
+ );
+ _Scheduler_Node_set_priority(
+ SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation ),
+ _Priority_Get_priority( priority_aggregation ),
+ prepend_it
+ );
+}
+
+static void _Thread_queue_Priority_add(
+ Thread_Control *the_thread,
+ Priority_Aggregation *priority_aggregation,
+ Priority_Node *priority_node,
+ Thread_queue_Context *queue_context
+)
+{
+ _Priority_Non_empty_insert(
+ priority_aggregation,
+ priority_node,
+ &queue_context->Priority.Actions,
+ _Thread_queue_Priority_inherit_do_surrender_change,
+ the_thread
+ );
+}
+
+static void _Thread_queue_Priority_remove(
+ Thread_Control *the_thread,
+ Scheduler_Node *scheduler_node,
+ Priority_Node *priority_node,
+ Thread_queue_Context *queue_context
+)
+{
+ _Priority_Extract_non_empty(
+ &scheduler_node->Wait.Priority,
+ priority_node,
+ &queue_context->Priority.Actions,
+ _Thread_queue_Priority_inherit_do_surrender_change,
+ the_thread
+ );
+}
+
+static void _Thread_queue_Priority_inherit_do_surrender(
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *previous_owner,
+ Thread_queue_Context *queue_context,
+ Thread_Control *the_thread
+)
+{
+ Scheduler_Node *scheduler_node;
+ Thread_queue_Priority_queue *priority_queue;
+ ISR_lock_Context lock_context;
+
+ scheduler_node = _Thread_Scheduler_get_own_node( the_thread );
+ priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
+
+ _Thread_Wait_acquire_default_critical( previous_owner, &lock_context );
+
#if defined(RTEMS_SMP)
- if ( !_Chain_Has_only_one_node( &heads->Heads.Fifo ) ) {
- const Scheduler_Control *scheduler;
- Priority_Control boost_priority;
+ if ( _Priority_Node_is_active( &heads->Boost_priority ) ) {
+ _Thread_queue_Priority_remove(
+ previous_owner,
+ _Thread_Scheduler_get_own_node( previous_owner ),
+ &heads->Boost_priority,
+ queue_context
+ );
+ _Priority_Node_set_inactive( &heads->Boost_priority );
+ }
+#endif
- the_thread->priority_restore_hint = true;
- _Atomic_Fence( ATOMIC_ORDER_ACQ_REL );
+ _Thread_queue_Priority_remove(
+ previous_owner,
+ priority_queue->scheduler_node,
+ &priority_queue->Queue.Node,
+ queue_context
+ );
- scheduler = _Scheduler_Get_own( the_thread );
- boost_priority = _Scheduler_Map_priority( scheduler, PRIORITY_PSEUDO_ISR );
+ _Thread_Wait_release_default_critical( previous_owner, &lock_context );
- _Scheduler_Thread_set_priority( the_thread, boost_priority, false );
+ _Priority_Extract(
+ &priority_queue->Queue,
+ &scheduler_node->Wait.Priority.Node,
+ NULL,
+ _Priority_Remove_nothing,
+ _Priority_Change_nothing,
+ previous_owner
+ );
+
+ if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+ priority_queue->scheduler_node = scheduler_node;
+ _Thread_queue_Priority_add(
+ the_thread,
+ &scheduler_node->Wait.Priority,
+ &priority_queue->Queue.Node,
+ queue_context
+ );
+ }
+
+#if defined(RTEMS_SMP)
+ _Chain_Extract_unprotected( &priority_queue->Node );
+
+ if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
+ _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
+ }
+
+ if (
+ !_Chain_Is_empty( &heads->Heads.Fifo)
+ && !_Chain_Has_only_one_node( &heads->Heads.Fifo)
+ ) {
+ Priority_Control boost_priority;
+
+ boost_priority = _Scheduler_Map_priority(
+ _Scheduler_Get_own( the_thread ),
+ PRIORITY_PSEUDO_ISR
+ );
+ _Priority_Node_initialize( &heads->Boost_priority, boost_priority );
+ _Thread_queue_Priority_add(
+ the_thread,
+ &scheduler_node->Wait.Priority,
+ &heads->Boost_priority,
+ queue_context
+ );
}
-#else
- (void) heads;
- (void) the_thread;
#endif
}
static Thread_Control *_Thread_queue_Priority_inherit_surrender(
- Thread_queue_Queue *queue,
- Thread_queue_Heads *heads,
- Thread_Control *previous_owner
+ Thread_queue_Queue *queue,
+ Thread_queue_Heads *heads,
+ Thread_Control *previous_owner,
+ Thread_queue_Context *queue_context
)
{
Thread_Control *first;
first = _Thread_queue_Priority_first( heads );
- _Thread_queue_Boost_priority( heads, first );
_Thread_queue_Queue_extract(
queue,
heads,
+ previous_owner,
+ queue_context,
first,
- _Thread_queue_Priority_do_extract
+ _Thread_queue_Priority_inherit_do_surrender
);
return first;
}
const Thread_queue_Operations _Thread_queue_Operations_default = {
- .priority_change = _Thread_queue_Do_nothing_priority_change,
+ .priority_actions = _Thread_queue_Do_nothing_priority_actions,
.extract = _Thread_queue_Do_nothing_extract
/*
* The default operations are only used in _Thread_Change_priority() and
@@ -516,7 +991,7 @@ const Thread_queue_Operations _Thread_queue_Operations_default = {
};
const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
- .priority_change = _Thread_queue_Do_nothing_priority_change,
+ .priority_actions = _Thread_queue_Do_nothing_priority_actions,
.enqueue = _Thread_queue_FIFO_enqueue,
.extract = _Thread_queue_FIFO_extract,
.surrender = _Thread_queue_FIFO_surrender,
@@ -524,7 +999,7 @@ const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
};
const Thread_queue_Operations _Thread_queue_Operations_priority = {
- .priority_change = _Thread_queue_Priority_priority_change,
+ .priority_actions = _Thread_queue_Priority_priority_actions,
.enqueue = _Thread_queue_Priority_enqueue,
.extract = _Thread_queue_Priority_extract,
.surrender = _Thread_queue_Priority_surrender,
@@ -532,9 +1007,9 @@ const Thread_queue_Operations _Thread_queue_Operations_priority = {
};
const Thread_queue_Operations _Thread_queue_Operations_priority_inherit = {
- .priority_change = _Thread_queue_Priority_priority_change,
+ .priority_actions = _Thread_queue_Priority_inherit_priority_actions,
.enqueue = _Thread_queue_Priority_inherit_enqueue,
- .extract = _Thread_queue_Priority_extract,
+ .extract = _Thread_queue_Priority_inherit_extract,
.surrender = _Thread_queue_Priority_inherit_surrender,
.first = _Thread_queue_Priority_first
};