File indexing completed on 2025-05-11 08:24:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #ifdef HAVE_CONFIG_H
0044 #include "config.h"
0045 #endif
0046
0047 #include <rtems/score/threadimpl.h>
0048 #include <rtems/score/assert.h>
0049 #include <rtems/score/schedulerimpl.h>
0050
0051 static void _Thread_Set_scheduler_node_priority(
0052 Priority_Aggregation *priority_aggregation,
0053 Priority_Group_order priority_group_order
0054 )
0055 {
0056 _Scheduler_Node_set_priority(
0057 SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( priority_aggregation ),
0058 _Priority_Get_priority( priority_aggregation ),
0059 priority_group_order
0060 );
0061 }
0062
0063 #if defined(RTEMS_SMP)
0064 static void _Thread_Priority_action_add(
0065 Priority_Aggregation *priority_aggregation,
0066 Priority_Actions *priority_actions,
0067 void *arg
0068 )
0069 {
0070 Scheduler_Node *scheduler_node;
0071 Thread_Control *the_thread;
0072
0073 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
0074 the_thread = arg;
0075
0076 _Thread_Scheduler_add_wait_node( the_thread, scheduler_node );
0077 _Thread_Set_scheduler_node_priority(
0078 priority_aggregation,
0079 PRIORITY_GROUP_LAST
0080 );
0081 _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_ADD );
0082 _Priority_Actions_add( priority_actions, priority_aggregation );
0083 }
0084
0085 static void _Thread_Priority_action_remove(
0086 Priority_Aggregation *priority_aggregation,
0087 Priority_Actions *priority_actions,
0088 void *arg
0089 )
0090 {
0091 Scheduler_Node *scheduler_node;
0092 Thread_Control *the_thread;
0093
0094 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
0095 the_thread = arg;
0096
0097 _Thread_Scheduler_remove_wait_node( the_thread, scheduler_node );
0098 _Thread_Set_scheduler_node_priority(
0099 priority_aggregation,
0100 PRIORITY_GROUP_FIRST
0101 );
0102 _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_REMOVE );
0103 _Priority_Actions_add( priority_actions, priority_aggregation );
0104 }
0105 #endif
0106
0107 static void _Thread_Priority_action_change(
0108 Priority_Aggregation *priority_aggregation,
0109 Priority_Group_order priority_group_order,
0110 Priority_Actions *priority_actions,
0111 void *arg
0112 )
0113 {
0114 (void) arg;
0115 _Thread_Set_scheduler_node_priority(
0116 priority_aggregation,
0117 priority_group_order
0118 );
0119 #if defined(RTEMS_SMP) || defined(RTEMS_DEBUG)
0120 _Priority_Set_action_type( priority_aggregation, PRIORITY_ACTION_CHANGE );
0121 #endif
0122 _Priority_Actions_add( priority_actions, priority_aggregation );
0123 }
0124
0125 static void _Thread_Priority_do_perform_actions(
0126 Thread_Control *the_thread,
0127 Thread_queue_Queue *queue,
0128 const Thread_queue_Operations *operations,
0129 Priority_Group_order priority_group_order,
0130 Thread_queue_Context *queue_context
0131 )
0132 {
0133 Priority_Aggregation *priority_aggregation;
0134
0135 _Assert( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) );
0136 priority_aggregation = _Priority_Actions_move( &queue_context->Priority.Actions );
0137
0138 do {
0139 #if defined(RTEMS_SMP)
0140 Priority_Aggregation *next_aggregation;
0141 #endif
0142 Priority_Node *priority_action_node;
0143 Priority_Action_type priority_action_type;
0144
0145 #if defined(RTEMS_SMP)
0146 next_aggregation = _Priority_Get_next_action( priority_aggregation );
0147 #endif
0148
0149 priority_action_node = priority_aggregation->Action.node;
0150 priority_action_type = priority_aggregation->Action.type;
0151
0152 switch ( priority_action_type ) {
0153 case PRIORITY_ACTION_ADD:
0154 #if defined(RTEMS_SMP)
0155 _Priority_Insert(
0156 priority_aggregation,
0157 priority_action_node,
0158 &queue_context->Priority.Actions,
0159 _Thread_Priority_action_add,
0160 _Thread_Priority_action_change,
0161 the_thread
0162 );
0163 #else
0164 _Priority_Non_empty_insert(
0165 priority_aggregation,
0166 priority_action_node,
0167 &queue_context->Priority.Actions,
0168 _Thread_Priority_action_change,
0169 NULL
0170 );
0171 #endif
0172 break;
0173 case PRIORITY_ACTION_REMOVE:
0174 #if defined(RTEMS_SMP)
0175 _Priority_Extract(
0176 priority_aggregation,
0177 priority_action_node,
0178 &queue_context->Priority.Actions,
0179 _Thread_Priority_action_remove,
0180 _Thread_Priority_action_change,
0181 the_thread
0182 );
0183 #else
0184 _Priority_Extract_non_empty(
0185 priority_aggregation,
0186 priority_action_node,
0187 &queue_context->Priority.Actions,
0188 _Thread_Priority_action_change,
0189 NULL
0190 );
0191 #endif
0192 break;
0193 default:
0194 _Assert( priority_action_type == PRIORITY_ACTION_CHANGE );
0195 _Priority_Changed(
0196 priority_aggregation,
0197 priority_action_node,
0198 priority_group_order,
0199 &queue_context->Priority.Actions,
0200 _Thread_Priority_action_change,
0201 NULL
0202 );
0203 break;
0204 }
0205
0206 #if defined(RTEMS_SMP)
0207 priority_aggregation = next_aggregation;
0208 } while ( priority_aggregation != NULL );
0209 #else
0210 } while ( false );
0211 #endif
0212
0213 if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
0214 _Thread_queue_Context_add_priority_update( queue_context, the_thread );
0215
0216 ( *operations->priority_actions )(
0217 queue,
0218 &queue_context->Priority.Actions
0219 );
0220 }
0221 }
0222
0223 void _Thread_Priority_perform_actions(
0224 Thread_Control *start_of_path,
0225 Thread_queue_Context *queue_context
0226 )
0227 {
0228 Thread_Control *the_thread;
0229 size_t update_count;
0230
0231 _Assert( start_of_path != NULL );
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242 the_thread = start_of_path;
0243 update_count = _Thread_queue_Context_get_priority_updates( queue_context );
0244
0245 while ( true ) {
0246 Thread_queue_Queue *queue;
0247
0248 queue = the_thread->Wait.queue;
0249
0250 _Thread_Priority_do_perform_actions(
0251 the_thread,
0252 queue,
0253 the_thread->Wait.operations,
0254 PRIORITY_GROUP_LAST,
0255 queue_context
0256 );
0257
0258 if ( _Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
0259 return;
0260 }
0261
0262 _Assert( queue != NULL );
0263 the_thread = queue->owner;
0264 _Assert( the_thread != NULL );
0265
0266
0267
0268
0269
0270
0271
0272
0273 _Thread_queue_Context_restore_priority_updates(
0274 queue_context,
0275 update_count
0276 );
0277 }
0278 }
0279
0280 static void _Thread_Priority_apply(
0281 Thread_Control *the_thread,
0282 Priority_Node *priority_action_node,
0283 Thread_queue_Context *queue_context,
0284 Priority_Group_order priority_group_order,
0285 Priority_Action_type priority_action_type
0286 )
0287 {
0288 Scheduler_Node *scheduler_node;
0289 Thread_queue_Queue *queue;
0290
0291 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0292 _Priority_Actions_initialize_one(
0293 &queue_context->Priority.Actions,
0294 &scheduler_node->Wait.Priority,
0295 priority_action_node,
0296 priority_action_type
0297 );
0298 queue = the_thread->Wait.queue;
0299
0300 #if defined(RTEMS_SMP)
0301 if ( queue != NULL ) {
0302
0303
0304
0305
0306
0307
0308
0309 (void) _Thread_queue_Path_acquire( queue, the_thread, queue_context );
0310 }
0311 #endif
0312
0313 _Thread_Priority_do_perform_actions(
0314 the_thread,
0315 queue,
0316 the_thread->Wait.operations,
0317 priority_group_order,
0318 queue_context
0319 );
0320
0321 if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
0322 _Thread_Priority_perform_actions( queue->owner, queue_context );
0323 }
0324
0325 #if defined(RTEMS_SMP)
0326 if (queue != NULL ) {
0327 _Thread_queue_Path_release( queue_context );
0328 }
0329 #endif
0330 }
0331
0332 void _Thread_Priority_add(
0333 Thread_Control *the_thread,
0334 Priority_Node *priority_node,
0335 Thread_queue_Context *queue_context
0336 )
0337 {
0338 _Thread_Priority_apply(
0339 the_thread,
0340 priority_node,
0341 queue_context,
0342 PRIORITY_GROUP_LAST,
0343 PRIORITY_ACTION_ADD
0344 );
0345 }
0346
0347 void _Thread_Priority_remove(
0348 Thread_Control *the_thread,
0349 Priority_Node *priority_node,
0350 Thread_queue_Context *queue_context
0351 )
0352 {
0353 _Thread_Priority_apply(
0354 the_thread,
0355 priority_node,
0356 queue_context,
0357 PRIORITY_GROUP_FIRST,
0358 PRIORITY_ACTION_REMOVE
0359 );
0360 }
0361
0362 void _Thread_Priority_changed(
0363 Thread_Control *the_thread,
0364 Priority_Node *priority_node,
0365 Priority_Group_order priority_group_order,
0366 Thread_queue_Context *queue_context
0367 )
0368 {
0369 _Thread_Priority_apply(
0370 the_thread,
0371 priority_node,
0372 queue_context,
0373 priority_group_order,
0374 PRIORITY_ACTION_CHANGE
0375 );
0376 }
0377
0378 #if defined(RTEMS_SMP)
0379 void _Thread_Priority_replace(
0380 Thread_Control *the_thread,
0381 Priority_Node *victim_node,
0382 Priority_Node *replacement_node
0383 )
0384 {
0385 Scheduler_Node *scheduler_node;
0386
0387 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0388 _Priority_Replace(
0389 &scheduler_node->Wait.Priority,
0390 victim_node,
0391 replacement_node
0392 );
0393 }
0394 #endif
0395
0396 void _Thread_Priority_update( Thread_queue_Context *queue_context )
0397 {
0398 size_t i;
0399 size_t n;
0400
0401 n = queue_context->Priority.update_count;
0402
0403
0404
0405
0406
0407 for ( i = 0; i < n ; ++i ) {
0408 Thread_Control *the_thread;
0409 ISR_lock_Context lock_context;
0410
0411 the_thread = queue_context->Priority.update[ i ];
0412 _Thread_State_acquire( the_thread, &lock_context );
0413 _Scheduler_Update_priority( the_thread );
0414 _Thread_State_release( the_thread, &lock_context );
0415 }
0416 }
0417
0418 #if defined(RTEMS_SMP)
0419 static void _Thread_Priority_update_helping(
0420 Thread_Control *the_thread,
0421 Chain_Node *first_node
0422 )
0423 {
0424 const Chain_Node *tail;
0425 Chain_Node *node;
0426
0427 tail = _Chain_Immutable_tail( &the_thread->Scheduler.Scheduler_nodes );
0428 node = _Chain_Next( first_node );
0429
0430 while ( node != tail ) {
0431 Scheduler_Node *scheduler_node;
0432 const Scheduler_Control *scheduler;
0433 ISR_lock_Context lock_context;
0434
0435 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
0436 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
0437
0438 _Scheduler_Acquire_critical( scheduler, &lock_context );
0439 ( *scheduler->Operations.update_priority )(
0440 scheduler,
0441 the_thread,
0442 scheduler_node
0443 );
0444 _Scheduler_Release_critical( scheduler, &lock_context );
0445
0446 node = _Chain_Next( node );
0447 }
0448 }
0449
0450 void _Thread_Priority_update_and_make_sticky( Thread_Control *the_thread )
0451 {
0452 ISR_lock_Context lock_context;
0453 ISR_lock_Context lock_context_2;
0454 Chain_Node *node;
0455 Scheduler_Node *scheduler_node;
0456 const Scheduler_Control *scheduler;
0457 int new_sticky_level;
0458 int make_sticky_level;
0459
0460 _Thread_State_acquire( the_thread, &lock_context );
0461 _Thread_Scheduler_process_requests( the_thread );
0462
0463 node = _Chain_First( &the_thread->Scheduler.Scheduler_nodes );
0464 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
0465 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
0466
0467 _Scheduler_Acquire_critical( scheduler, &lock_context_2 );
0468
0469 new_sticky_level = scheduler_node->sticky_level + 1;
0470 scheduler_node->sticky_level = new_sticky_level;
0471 _Assert( new_sticky_level >= 1 );
0472
0473
0474
0475
0476
0477 make_sticky_level = 1 + (int) _Thread_Is_ready( the_thread );
0478
0479 if ( new_sticky_level == make_sticky_level ) {
0480 ( *scheduler->Operations.make_sticky )(
0481 scheduler,
0482 the_thread,
0483 scheduler_node
0484 );
0485 }
0486
0487 ( *scheduler->Operations.update_priority )(
0488 scheduler,
0489 the_thread,
0490 scheduler_node
0491 );
0492
0493 _Scheduler_Release_critical( scheduler, &lock_context_2 );
0494 _Thread_Priority_update_helping( the_thread, node );
0495 _Thread_State_release( the_thread, &lock_context );
0496 }
0497
0498 void _Thread_Priority_update_and_clean_sticky( Thread_Control *the_thread )
0499 {
0500 ISR_lock_Context lock_context;
0501 ISR_lock_Context lock_context_2;
0502 Chain_Node *node;
0503 Scheduler_Node *scheduler_node;
0504 const Scheduler_Control *scheduler;
0505 int new_sticky_level;
0506 int clean_sticky_level;
0507
0508 _Thread_State_acquire( the_thread, &lock_context );
0509 _Thread_Scheduler_process_requests( the_thread );
0510
0511 node = _Chain_First( &the_thread->Scheduler.Scheduler_nodes );
0512 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
0513 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
0514
0515 _Scheduler_Acquire_critical( scheduler, &lock_context_2 );
0516
0517 new_sticky_level = scheduler_node->sticky_level - 1;
0518 scheduler_node->sticky_level = new_sticky_level;
0519 _Assert( new_sticky_level >= 0 );
0520
0521
0522
0523
0524
0525 clean_sticky_level = (int) _Thread_Is_ready( the_thread );
0526
0527 if ( new_sticky_level == clean_sticky_level ) {
0528 ( *scheduler->Operations.clean_sticky )(
0529 scheduler,
0530 the_thread,
0531 scheduler_node
0532 );
0533 }
0534
0535 ( *scheduler->Operations.update_priority )(
0536 scheduler,
0537 the_thread,
0538 scheduler_node
0539 );
0540
0541 _Scheduler_Release_critical( scheduler, &lock_context_2 );
0542 _Thread_Priority_update_helping( the_thread, node );
0543 _Thread_State_release( the_thread, &lock_context );
0544 }
0545
0546 void _Thread_Priority_update_ignore_sticky( Thread_Control *the_thread )
0547 {
0548 ISR_lock_Context lock_context;
0549
0550 _Thread_State_acquire( the_thread, &lock_context );
0551 _Thread_Scheduler_process_requests( the_thread );
0552 _Scheduler_Update_priority( the_thread );
0553 _Thread_State_release( the_thread, &lock_context );
0554 }
0555 #endif