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 #ifdef HAVE_CONFIG_H
0040 #include "config.h"
0041 #endif
0042
0043 #include <rtems/score/threadqops.h>
0044 #include <rtems/score/threadimpl.h>
0045 #include <rtems/score/assert.h>
0046 #include <rtems/score/chainimpl.h>
0047 #include <rtems/score/rbtreeimpl.h>
0048 #include <rtems/score/schedulerimpl.h>
0049
0050 #define THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ) \
0051 RTEMS_CONTAINER_OF( \
0052 priority_actions, \
0053 Thread_queue_Context, \
0054 Priority.Actions \
0055 )
0056
0057 #define THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION( \
0058 priority_aggregation \
0059 ) \
0060 RTEMS_CONTAINER_OF( \
0061 priority_aggregation, \
0062 Thread_queue_Priority_queue, \
0063 Queue \
0064 )
0065
0066 void _Thread_queue_Do_nothing_priority_actions(
0067 Thread_queue_Queue *queue,
0068 Priority_Actions *priority_actions
0069 )
0070 {
0071 #if defined(RTEMS_DEBUG) && defined(RTEMS_SMP)
0072 Priority_Aggregation *priority_aggregation;
0073
0074 priority_aggregation = _Priority_Actions_move( priority_actions );
0075
0076 while ( priority_aggregation != NULL ) {
0077 priority_aggregation = _Priority_Get_next_action( priority_aggregation );
0078 }
0079 #endif
0080
0081 (void) queue;
0082 _Priority_Actions_initialize_empty( priority_actions );
0083 }
0084
0085 static void _Thread_queue_Queue_enqueue(
0086 Thread_queue_Queue *queue,
0087 Thread_Control *the_thread,
0088 Thread_queue_Context *queue_context,
0089 void ( *initialize )(
0090 Thread_queue_Queue *,
0091 Thread_Control *,
0092 Thread_queue_Context *,
0093 Thread_queue_Heads *
0094 ),
0095 void ( *enqueue )(
0096 Thread_queue_Queue *,
0097 Thread_Control *,
0098 Thread_queue_Context *,
0099 Thread_queue_Heads *
0100 )
0101 )
0102 {
0103 Thread_queue_Heads *heads;
0104 Thread_queue_Heads *spare_heads;
0105
0106 heads = queue->heads;
0107 spare_heads = the_thread->Wait.spare_heads;
0108 the_thread->Wait.spare_heads = NULL;
0109
0110 if ( heads == NULL ) {
0111 _Assert( spare_heads != NULL );
0112 _Assert( _Chain_Is_empty( &spare_heads->Free_chain ) );
0113
0114 heads = spare_heads;
0115 queue->heads = heads;
0116 _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
0117 ( *initialize )( queue, the_thread, queue_context, heads );
0118 } else {
0119 _Chain_Prepend_unprotected( &heads->Free_chain, &spare_heads->Free_node );
0120 ( *enqueue )( queue, the_thread, queue_context, heads );
0121 }
0122 }
0123
0124 static void _Thread_queue_Queue_extract(
0125 Thread_queue_Queue *queue,
0126 Thread_queue_Heads *heads,
0127 Thread_Control *current_or_previous_owner,
0128 Thread_queue_Context *queue_context,
0129 Thread_Control *the_thread,
0130 void ( *extract )(
0131 Thread_queue_Queue *,
0132 Thread_queue_Heads *,
0133 Thread_Control *,
0134 Thread_queue_Context *,
0135 Thread_Control *
0136 )
0137 )
0138 {
0139 _Assert( heads != NULL );
0140
0141 the_thread->Wait.spare_heads = RTEMS_CONTAINER_OF(
0142 _Chain_Get_first_unprotected( &heads->Free_chain ),
0143 Thread_queue_Heads,
0144 Free_node
0145 );
0146
0147 if ( _Chain_Is_empty( &heads->Free_chain ) ) {
0148 queue->heads = NULL;
0149 }
0150
0151 ( *extract )(
0152 queue,
0153 heads,
0154 current_or_previous_owner,
0155 queue_context,
0156 the_thread
0157 );
0158 }
0159
0160 static void _Thread_queue_FIFO_do_initialize(
0161 Thread_queue_Queue *queue,
0162 Thread_Control *the_thread,
0163 Thread_queue_Context *queue_context,
0164 Thread_queue_Heads *heads
0165 )
0166 {
0167 Scheduler_Node *scheduler_node;
0168
0169 (void) queue;
0170 (void) queue_context;
0171 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0172
0173 _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
0174 _Chain_Initialize_one(
0175 &heads->Heads.Fifo,
0176 &scheduler_node->Wait.Priority.Node.Node.Chain
0177 );
0178 }
0179
0180 static void _Thread_queue_FIFO_do_enqueue(
0181 Thread_queue_Queue *queue,
0182 Thread_Control *the_thread,
0183 Thread_queue_Context *queue_context,
0184 Thread_queue_Heads *heads
0185 )
0186 {
0187 Scheduler_Node *scheduler_node;
0188
0189 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0190
0191 _Chain_Initialize_node( &scheduler_node->Wait.Priority.Node.Node.Chain );
0192 _Chain_Append_unprotected(
0193 &heads->Heads.Fifo,
0194 &scheduler_node->Wait.Priority.Node.Node.Chain
0195 );
0196 }
0197
0198 static void _Thread_queue_FIFO_do_extract(
0199 Thread_queue_Queue *queue,
0200 Thread_queue_Heads *heads,
0201 Thread_Control *current_or_previous_owner,
0202 Thread_queue_Context *queue_context,
0203 Thread_Control *the_thread
0204 )
0205 {
0206 Scheduler_Node *scheduler_node;
0207
0208 (void) current_or_previous_owner;
0209 (void) queue_context;
0210
0211 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0212
0213 _Chain_Extract_unprotected( &scheduler_node->Wait.Priority.Node.Node.Chain );
0214 }
0215
0216 void _Thread_queue_FIFO_enqueue(
0217 Thread_queue_Queue *queue,
0218 Thread_Control *the_thread,
0219 Thread_queue_Context *queue_context
0220 )
0221 {
0222 _Thread_queue_Queue_enqueue(
0223 queue,
0224 the_thread,
0225 queue_context,
0226 _Thread_queue_FIFO_do_initialize,
0227 _Thread_queue_FIFO_do_enqueue
0228 );
0229 }
0230
0231 void _Thread_queue_FIFO_extract(
0232 Thread_queue_Queue *queue,
0233 Thread_Control *the_thread,
0234 Thread_queue_Context *queue_context
0235 )
0236 {
0237 _Thread_queue_Queue_extract(
0238 queue,
0239 queue->heads,
0240 NULL,
0241 queue_context,
0242 the_thread,
0243 _Thread_queue_FIFO_do_extract
0244 );
0245 }
0246
0247 Thread_Control *_Thread_queue_FIFO_first( const Thread_queue_Heads *heads )
0248 {
0249 const Chain_Control *fifo;
0250 const Chain_Node *first;
0251 const Scheduler_Node *scheduler_node;
0252
0253 fifo = &heads->Heads.Fifo;
0254 _Assert( !_Chain_Is_empty( fifo ) );
0255 first = _Chain_Immutable_first( fifo );
0256 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
0257
0258 return _Scheduler_Node_get_owner( scheduler_node );
0259 }
0260
0261 Thread_Control *_Thread_queue_FIFO_surrender(
0262 Thread_queue_Queue *queue,
0263 Thread_queue_Heads *heads,
0264 Thread_Control *previous_owner,
0265 Thread_queue_Context *queue_context
0266 )
0267 {
0268 Thread_Control *first;
0269
0270 (void) previous_owner;
0271
0272 first = _Thread_queue_FIFO_first( heads );
0273 _Thread_queue_Queue_extract(
0274 queue,
0275 heads,
0276 NULL,
0277 queue_context,
0278 first,
0279 _Thread_queue_FIFO_do_extract
0280 );
0281
0282 return first;
0283 }
0284
0285 static size_t _Thread_queue_Scheduler_index(
0286 const Scheduler_Node *scheduler_node
0287 )
0288 {
0289 #if defined(RTEMS_SMP)
0290 const Scheduler_Control *scheduler;
0291
0292 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
0293 return _Scheduler_Get_index( scheduler );
0294 #else
0295 (void) scheduler_node;
0296 return 0;
0297 #endif
0298 }
0299
0300 static Thread_queue_Priority_queue *_Thread_queue_Priority_queue_by_index(
0301 Thread_queue_Heads *heads,
0302 size_t scheduler_index
0303 )
0304 {
0305 #if defined(RTEMS_SMP)
0306 _Assert( scheduler_index < _Scheduler_Count );
0307 return &heads->Priority[ scheduler_index ];
0308 #else
0309 (void) scheduler_index;
0310 return &heads->Heads.Priority;
0311 #endif
0312 }
0313
0314 static Thread_queue_Priority_queue *_Thread_queue_Priority_queue(
0315 Thread_queue_Heads *heads,
0316 const Scheduler_Node *scheduler_node
0317 )
0318 {
0319 return _Thread_queue_Priority_queue_by_index(
0320 heads,
0321 _Thread_queue_Scheduler_index( scheduler_node )
0322 );
0323 }
0324
0325 static Chain_Node *_Thread_queue_Priority_queue_rotation(
0326 Thread_queue_Heads *heads
0327 )
0328 {
0329 Chain_Node *fifo_node;
0330
0331 #if defined(RTEMS_SMP)
0332
0333 fifo_node = _Chain_First( &heads->Heads.Fifo );
0334 _Chain_Extract_unprotected( fifo_node );
0335 _Chain_Append_unprotected( &heads->Heads.Fifo, fifo_node );
0336 #else
0337 (void) heads;
0338 fifo_node = NULL;
0339 #endif
0340
0341 return fifo_node;
0342 }
0343
0344 #if defined(RTEMS_SMP)
0345 static void _Thread_queue_Priority_queue_extract(
0346 Priority_Aggregation *priority_aggregation,
0347 Priority_Actions *priority_actions,
0348 void *arg
0349 )
0350 {
0351 Thread_queue_Priority_queue *priority_queue;
0352
0353 (void) priority_actions;
0354 (void) arg;
0355
0356 priority_queue = THREAD_QUEUE_PRIORITY_QUEUE_OF_PRIORITY_AGGREGATION(
0357 priority_aggregation
0358 );
0359
0360 _Chain_Extract_unprotected( &priority_queue->Node );
0361 }
0362 #endif
0363
0364 static void _Thread_queue_Priority_priority_actions(
0365 Thread_queue_Queue *queue,
0366 Priority_Actions *priority_actions
0367 )
0368 {
0369 Thread_queue_Heads *heads;
0370 Priority_Aggregation *priority_aggregation;
0371
0372 heads = queue->heads;
0373 _Assert( heads != NULL );
0374
0375 _Assert( !_Priority_Actions_is_empty( priority_actions ) );
0376 priority_aggregation = _Priority_Actions_move( priority_actions );
0377
0378 do {
0379 #if defined(RTEMS_SMP)
0380 Priority_Aggregation *next_aggregation;
0381 #endif
0382 Scheduler_Node *scheduler_node;
0383 Thread_queue_Priority_queue *priority_queue;
0384 Priority_Action_type priority_action_type;
0385
0386 #if defined(RTEMS_SMP)
0387 next_aggregation = _Priority_Get_next_action( priority_aggregation );
0388 #endif
0389
0390 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
0391 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0392 priority_action_type = priority_aggregation->Action.type;
0393
0394 switch ( priority_action_type ) {
0395 #if defined(RTEMS_SMP)
0396 case PRIORITY_ACTION_ADD:
0397 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0398 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0399 }
0400
0401 _Priority_Plain_insert(
0402 &priority_queue->Queue,
0403 &scheduler_node->Wait.Priority.Node,
0404 _Priority_Get_priority( &scheduler_node->Wait.Priority )
0405 );
0406 break;
0407 case PRIORITY_ACTION_REMOVE:
0408 _Priority_Plain_extract(
0409 &priority_queue->Queue,
0410 &scheduler_node->Wait.Priority.Node
0411 );
0412
0413 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0414 _Chain_Extract_unprotected( &priority_queue->Node );
0415 }
0416 break;
0417 #endif
0418 default:
0419 _Assert( priority_action_type == PRIORITY_ACTION_CHANGE );
0420 _Priority_Plain_changed(
0421 &priority_queue->Queue,
0422 &scheduler_node->Wait.Priority.Node
0423 );
0424 break;
0425 }
0426
0427 #if defined(RTEMS_SMP)
0428 priority_aggregation = next_aggregation;
0429 } while ( priority_aggregation != NULL );
0430 #else
0431 } while ( false );
0432 #endif
0433 }
0434
0435 static void _Thread_queue_Priority_do_initialize(
0436 Thread_queue_Queue *queue,
0437 Thread_Control *the_thread,
0438 Thread_queue_Context *queue_context,
0439 Thread_queue_Heads *heads
0440 )
0441 {
0442 Scheduler_Node *scheduler_node;
0443 Thread_queue_Priority_queue *priority_queue;
0444 #if defined(RTEMS_SMP)
0445 Chain_Node *wait_node;
0446 const Chain_Node *wait_tail;
0447 #endif
0448
0449 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0450 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0451
0452 _Priority_Initialize_one(
0453 &priority_queue->Queue,
0454 &scheduler_node->Wait.Priority.Node
0455 );
0456
0457 #if defined(RTEMS_SMP)
0458 _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
0459
0460 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0461 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
0462
0463 while ( wait_node != wait_tail ) {
0464 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
0465 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0466
0467 _Priority_Initialize_one(
0468 &priority_queue->Queue,
0469 &scheduler_node->Wait.Priority.Node
0470 );
0471 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0472
0473 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0474 }
0475 #endif
0476 }
0477
0478 static void _Thread_queue_Priority_do_enqueue(
0479 Thread_queue_Queue *queue,
0480 Thread_Control *the_thread,
0481 Thread_queue_Context *queue_context,
0482 Thread_queue_Heads *heads
0483 )
0484 {
0485 #if defined(RTEMS_SMP)
0486 Chain_Node *wait_node;
0487 const Chain_Node *wait_tail;
0488
0489 wait_node = _Chain_First( &the_thread->Scheduler.Wait_nodes );
0490 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
0491
0492 do {
0493 Scheduler_Node *scheduler_node;
0494 Thread_queue_Priority_queue *priority_queue;
0495
0496 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
0497 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0498
0499 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0500 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0501 _Priority_Initialize_one(
0502 &priority_queue->Queue,
0503 &scheduler_node->Wait.Priority.Node
0504 );
0505 } else {
0506 _Priority_Plain_insert(
0507 &priority_queue->Queue,
0508 &scheduler_node->Wait.Priority.Node,
0509 _Priority_Get_priority( &scheduler_node->Wait.Priority )
0510 );
0511 }
0512
0513 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0514 } while ( wait_node != wait_tail );
0515 #else
0516 Scheduler_Node *scheduler_node;
0517 Thread_queue_Priority_queue *priority_queue;
0518
0519 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0520 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0521
0522 _Priority_Plain_insert(
0523 &priority_queue->Queue,
0524 &scheduler_node->Wait.Priority.Node,
0525 _Priority_Get_priority( &scheduler_node->Wait.Priority )
0526 );
0527 #endif
0528 }
0529
0530 static void _Thread_queue_Priority_do_extract(
0531 Thread_queue_Queue *queue,
0532 Thread_queue_Heads *heads,
0533 Thread_Control *current_or_previous_owner,
0534 Thread_queue_Context *queue_context,
0535 Thread_Control *the_thread
0536 )
0537 {
0538 #if defined(RTEMS_SMP)
0539 Chain_Node *wait_node;
0540 const Chain_Node *wait_tail;
0541
0542 wait_node = _Chain_First( &the_thread->Scheduler.Wait_nodes );
0543 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
0544
0545 do {
0546 Scheduler_Node *scheduler_node;
0547 Thread_queue_Priority_queue *priority_queue;
0548
0549 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
0550 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0551
0552 _Priority_Plain_extract(
0553 &priority_queue->Queue,
0554 &scheduler_node->Wait.Priority.Node
0555 );
0556
0557 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0558 _Chain_Extract_unprotected( &priority_queue->Node );
0559 }
0560
0561 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0562 } while ( wait_node != wait_tail );
0563 #else
0564 Scheduler_Node *scheduler_node;
0565 Thread_queue_Priority_queue *priority_queue;
0566
0567 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0568 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
0569
0570 _Priority_Plain_extract(
0571 &priority_queue->Queue,
0572 &scheduler_node->Wait.Priority.Node
0573 );
0574 #endif
0575
0576 (void) current_or_previous_owner;
0577 (void) queue_context;
0578 }
0579
0580 static void _Thread_queue_Priority_do_surrender(
0581 Thread_queue_Queue *queue,
0582 Thread_queue_Heads *heads,
0583 Thread_Control *current_or_previous_owner,
0584 Thread_queue_Context *queue_context,
0585 Thread_Control *the_thread
0586 )
0587 {
0588 _Thread_queue_Priority_queue_rotation( heads );
0589 _Thread_queue_Priority_do_extract(
0590 queue,
0591 heads,
0592 current_or_previous_owner,
0593 queue_context,
0594 the_thread
0595 );
0596 }
0597
0598 static void _Thread_queue_Priority_enqueue(
0599 Thread_queue_Queue *queue,
0600 Thread_Control *the_thread,
0601 Thread_queue_Context *queue_context
0602 )
0603 {
0604 _Thread_queue_Queue_enqueue(
0605 queue,
0606 the_thread,
0607 queue_context,
0608 _Thread_queue_Priority_do_initialize,
0609 _Thread_queue_Priority_do_enqueue
0610 );
0611 }
0612
0613 static void _Thread_queue_Priority_extract(
0614 Thread_queue_Queue *queue,
0615 Thread_Control *the_thread,
0616 Thread_queue_Context *queue_context
0617 )
0618 {
0619 _Thread_queue_Queue_extract(
0620 queue,
0621 queue->heads,
0622 NULL,
0623 queue_context,
0624 the_thread,
0625 _Thread_queue_Priority_do_extract
0626 );
0627 }
0628
0629 static Thread_Control *_Thread_queue_Priority_first(
0630 const Thread_queue_Heads *heads
0631 )
0632 {
0633 const Thread_queue_Priority_queue *priority_queue;
0634 Priority_Node *first;
0635 Scheduler_Node *scheduler_node;
0636
0637 #if defined(RTEMS_SMP)
0638 _Assert( !_Chain_Is_empty( &heads->Heads.Fifo ) );
0639 priority_queue = (Thread_queue_Priority_queue *)
0640 _Chain_First( &heads->Heads.Fifo );
0641 #else
0642 priority_queue = &heads->Heads.Priority;
0643 #endif
0644
0645 _Assert( !_Priority_Is_empty( &priority_queue->Queue ) );
0646 first = _Priority_Get_minimum_node( &priority_queue->Queue );
0647 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY_NODE( first );
0648
0649 return _Scheduler_Node_get_owner( scheduler_node );
0650 }
0651
0652 static Thread_Control *_Thread_queue_Priority_surrender(
0653 Thread_queue_Queue *queue,
0654 Thread_queue_Heads *heads,
0655 Thread_Control *previous_owner,
0656 Thread_queue_Context *queue_context
0657 )
0658 {
0659 Thread_Control *first;
0660
0661 first = _Thread_queue_Priority_first( heads );
0662 _Thread_queue_Queue_extract(
0663 queue,
0664 heads,
0665 NULL,
0666 queue_context,
0667 first,
0668 _Thread_queue_Priority_do_surrender
0669 );
0670
0671 return first;
0672 }
0673
0674 static void _Thread_queue_Priority_inherit_do_priority_actions_action(
0675 Priority_Aggregation *priority_aggregation,
0676 Priority_Actions *priority_actions,
0677 Scheduler_Node *scheduler_node_of_owner,
0678 Priority_Action_type priority_action_type
0679 )
0680 {
0681 _Priority_Set_action(
0682 &scheduler_node_of_owner->Wait.Priority,
0683 &priority_aggregation->Node,
0684 priority_action_type
0685 );
0686 _Priority_Actions_add(
0687 priority_actions,
0688 &scheduler_node_of_owner->Wait.Priority
0689 );
0690 }
0691
0692 #if defined(RTEMS_SMP)
0693 static void _Thread_queue_Priority_inherit_do_priority_actions_add(
0694 Priority_Aggregation *priority_aggregation,
0695 Priority_Actions *priority_actions,
0696 void *arg
0697 )
0698 {
0699 _Thread_queue_Priority_inherit_do_priority_actions_action(
0700 priority_aggregation,
0701 priority_actions,
0702 arg,
0703 PRIORITY_ACTION_ADD
0704 );
0705 }
0706
0707 static void _Thread_queue_Priority_inherit_do_priority_actions_remove(
0708 Priority_Aggregation *priority_aggregation,
0709 Priority_Actions *priority_actions,
0710 void *arg
0711 )
0712 {
0713 _Thread_queue_Priority_queue_extract(
0714 priority_aggregation,
0715 priority_actions,
0716 arg
0717 );
0718 _Thread_queue_Priority_inherit_do_priority_actions_action(
0719 priority_aggregation,
0720 priority_actions,
0721 arg,
0722 PRIORITY_ACTION_REMOVE
0723 );
0724 }
0725 #endif
0726
0727 static void _Thread_queue_Priority_inherit_do_priority_actions_change(
0728 Priority_Aggregation *priority_aggregation,
0729 Priority_Group_order priority_group_order,
0730 Priority_Actions *priority_actions,
0731 void *arg
0732 )
0733 {
0734 _Thread_queue_Priority_inherit_do_priority_actions_action(
0735 priority_aggregation,
0736 priority_actions,
0737 arg,
0738 PRIORITY_ACTION_CHANGE
0739 );
0740 }
0741
0742 static void _Thread_queue_Priority_inherit_priority_actions(
0743 Thread_queue_Queue *queue,
0744 Priority_Actions *priority_actions
0745 )
0746 {
0747 Thread_queue_Heads *heads;
0748 Thread_Control *owner;
0749 Priority_Aggregation *priority_aggregation;
0750
0751 heads = queue->heads;
0752 _Assert( heads != NULL );
0753
0754 owner = queue->owner;
0755 _Assert( owner != NULL );
0756
0757 _Assert( !_Priority_Actions_is_empty( priority_actions ) );
0758 priority_aggregation = _Priority_Actions_move( priority_actions );
0759
0760 do {
0761 #if defined(RTEMS_SMP)
0762 Priority_Aggregation *next_aggregation;
0763 #endif
0764 Scheduler_Node *scheduler_node;
0765 size_t scheduler_index;
0766 Thread_queue_Priority_queue *priority_queue;
0767 Scheduler_Node *scheduler_node_of_owner;
0768 Priority_Action_type priority_action_type;
0769
0770 #if defined(RTEMS_SMP)
0771 next_aggregation = _Priority_Get_next_action( priority_aggregation );
0772 #endif
0773
0774 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
0775 scheduler_index = _Thread_queue_Scheduler_index( scheduler_node );
0776 priority_queue = _Thread_queue_Priority_queue_by_index(
0777 heads,
0778 scheduler_index
0779 );
0780 scheduler_node_of_owner = _Thread_Scheduler_get_node_by_index(
0781 owner,
0782 scheduler_index
0783 );
0784 priority_action_type = priority_aggregation->Action.type;
0785
0786 switch ( priority_action_type ) {
0787 #if defined(RTEMS_SMP)
0788 case PRIORITY_ACTION_ADD:
0789 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0790 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0791 priority_queue->scheduler_node = scheduler_node_of_owner;
0792 }
0793
0794 _Priority_Insert(
0795 &priority_queue->Queue,
0796 &scheduler_node->Wait.Priority.Node,
0797 priority_actions,
0798 _Thread_queue_Priority_inherit_do_priority_actions_add,
0799 _Thread_queue_Priority_inherit_do_priority_actions_change,
0800 scheduler_node_of_owner
0801 );
0802 break;
0803 case PRIORITY_ACTION_REMOVE:
0804 _Priority_Extract(
0805 &priority_queue->Queue,
0806 &scheduler_node->Wait.Priority.Node,
0807 priority_actions,
0808 _Thread_queue_Priority_inherit_do_priority_actions_remove,
0809 _Thread_queue_Priority_inherit_do_priority_actions_change,
0810 scheduler_node_of_owner
0811 );
0812
0813 break;
0814 #endif
0815 default:
0816 _Assert( priority_action_type == PRIORITY_ACTION_CHANGE );
0817 _Priority_Changed(
0818 &priority_queue->Queue,
0819 &scheduler_node->Wait.Priority.Node,
0820 PRIORITY_GROUP_LAST,
0821 priority_actions,
0822 _Thread_queue_Priority_inherit_do_priority_actions_change,
0823 scheduler_node_of_owner
0824 );
0825 break;
0826 }
0827
0828 #if defined(RTEMS_SMP)
0829 priority_aggregation = next_aggregation;
0830 } while ( priority_aggregation != NULL );
0831 #else
0832 } while ( false );
0833 #endif
0834 }
0835
0836 static void _Thread_queue_Priority_inherit_do_initialize(
0837 Thread_queue_Queue *queue,
0838 Thread_Control *the_thread,
0839 Thread_queue_Context *queue_context,
0840 Thread_queue_Heads *heads
0841 )
0842 {
0843 Scheduler_Node *scheduler_node;
0844 size_t scheduler_index;
0845 Thread_queue_Priority_queue *priority_queue;
0846 Thread_Control *owner;
0847 Scheduler_Node *scheduler_node_of_owner;
0848 #if defined(RTEMS_SMP)
0849 Chain_Node *wait_node;
0850 const Chain_Node *wait_tail;
0851 #endif
0852
0853 owner = queue->owner;
0854
0855 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
0856 scheduler_index = _Thread_queue_Scheduler_index( scheduler_node );
0857 priority_queue = _Thread_queue_Priority_queue_by_index(
0858 heads,
0859 scheduler_index
0860 );
0861 scheduler_node_of_owner = _Thread_Scheduler_get_node_by_index(
0862 owner,
0863 scheduler_index
0864 );
0865
0866 priority_queue->scheduler_node = scheduler_node_of_owner;
0867 _Priority_Initialize_one(
0868 &priority_queue->Queue,
0869 &scheduler_node->Wait.Priority.Node
0870 );
0871 _Priority_Actions_initialize_one(
0872 &queue_context->Priority.Actions,
0873 &scheduler_node_of_owner->Wait.Priority,
0874 &priority_queue->Queue.Node,
0875 PRIORITY_ACTION_ADD
0876 );
0877
0878 #if defined(RTEMS_SMP)
0879 _Chain_Initialize_one( &heads->Heads.Fifo, &priority_queue->Node );
0880
0881 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0882 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
0883
0884 while ( wait_node != wait_tail ) {
0885 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
0886 scheduler_index = _Thread_queue_Scheduler_index( scheduler_node );
0887 priority_queue = _Thread_queue_Priority_queue_by_index(
0888 heads,
0889 scheduler_index
0890 );
0891 scheduler_node_of_owner = _Thread_Scheduler_get_node_by_index(
0892 owner,
0893 scheduler_index
0894 );
0895
0896 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0897 priority_queue->scheduler_node = scheduler_node_of_owner;
0898 _Priority_Initialize_one(
0899 &priority_queue->Queue,
0900 &scheduler_node->Wait.Priority.Node
0901 );
0902 _Priority_Set_action(
0903 &scheduler_node_of_owner->Wait.Priority,
0904 &priority_queue->Queue.Node,
0905 PRIORITY_ACTION_ADD
0906 );
0907 _Priority_Actions_add(
0908 &queue_context->Priority.Actions,
0909 &scheduler_node_of_owner->Wait.Priority
0910 );
0911
0912 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
0913 }
0914 #endif
0915
0916 _Thread_Priority_perform_actions( owner, queue_context );
0917 }
0918
0919 static void _Thread_queue_Priority_inherit_do_enqueue_change(
0920 Priority_Aggregation *priority_aggregation,
0921 Priority_Group_order priority_group_order,
0922 Priority_Actions *priority_actions,
0923 void *arg
0924 )
0925 {
0926 #if defined(RTEMS_SMP)
0927 Scheduler_Node *scheduler_node_of_owner;
0928
0929 scheduler_node_of_owner = arg;
0930
0931 _Priority_Set_action(
0932 &scheduler_node_of_owner->Wait.Priority,
0933 &priority_aggregation->Node,
0934 PRIORITY_ACTION_CHANGE
0935 );
0936 _Priority_Actions_add(
0937 priority_actions,
0938 &scheduler_node_of_owner->Wait.Priority
0939 );
0940 #else
0941 Thread_queue_Queue *queue;
0942 Thread_Control *owner;
0943 Scheduler_Node *scheduler_node_of_owner;
0944 Thread_queue_Context *queue_context;
0945
0946 queue = arg;
0947 owner = queue->owner;
0948 scheduler_node_of_owner = _Thread_Scheduler_get_home_node( owner );
0949 queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
0950
0951 _Priority_Actions_initialize_one(
0952 &queue_context->Priority.Actions,
0953 &scheduler_node_of_owner->Wait.Priority,
0954 &priority_aggregation->Node,
0955 PRIORITY_ACTION_CHANGE
0956 );
0957 _Thread_Priority_perform_actions( owner, queue_context );
0958 #endif
0959 }
0960
0961 static void _Thread_queue_Priority_inherit_do_enqueue(
0962 Thread_queue_Queue *queue,
0963 Thread_Control *the_thread,
0964 Thread_queue_Context *queue_context,
0965 Thread_queue_Heads *heads
0966 )
0967 {
0968 #if defined(RTEMS_SMP)
0969 Thread_Control *owner;
0970 Chain_Node *wait_node;
0971 const Chain_Node *wait_tail;
0972
0973 owner = queue->owner;
0974 wait_node = _Chain_First( &the_thread->Scheduler.Wait_nodes );
0975 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
0976
0977 _Priority_Actions_initialize_empty( &queue_context->Priority.Actions );
0978
0979 do {
0980 Scheduler_Node *scheduler_node;
0981 size_t scheduler_index;
0982 Thread_queue_Priority_queue *priority_queue;
0983 Scheduler_Node *scheduler_node_of_owner;
0984
0985 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
0986 scheduler_index = _Thread_queue_Scheduler_index( scheduler_node );
0987 priority_queue = _Thread_queue_Priority_queue_by_index(
0988 heads,
0989 scheduler_index
0990 );
0991 scheduler_node_of_owner = _Thread_Scheduler_get_node_by_index(
0992 owner,
0993 scheduler_index
0994 );
0995
0996 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
0997 _Chain_Append_unprotected( &heads->Heads.Fifo, &priority_queue->Node );
0998 priority_queue->scheduler_node = scheduler_node_of_owner;
0999 _Priority_Initialize_one(
1000 &priority_queue->Queue,
1001 &scheduler_node->Wait.Priority.Node
1002 );
1003 _Priority_Set_action(
1004 &scheduler_node_of_owner->Wait.Priority,
1005 &priority_queue->Queue.Node,
1006 PRIORITY_ACTION_ADD
1007 );
1008 _Priority_Actions_add(
1009 &queue_context->Priority.Actions,
1010 &scheduler_node_of_owner->Wait.Priority
1011 );
1012 } else {
1013 _Priority_Non_empty_insert(
1014 &priority_queue->Queue,
1015 &scheduler_node->Wait.Priority.Node,
1016 &queue_context->Priority.Actions,
1017 _Thread_queue_Priority_inherit_do_enqueue_change,
1018 scheduler_node_of_owner
1019 );
1020 }
1021
1022 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
1023 } while ( wait_node != wait_tail );
1024
1025 if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
1026 _Thread_Priority_perform_actions( owner, queue_context );
1027 }
1028 #else
1029 Scheduler_Node *scheduler_node;
1030 Thread_queue_Priority_queue *priority_queue;
1031
1032 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
1033 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
1034
1035 _Priority_Non_empty_insert(
1036 &priority_queue->Queue,
1037 &scheduler_node->Wait.Priority.Node,
1038 &queue_context->Priority.Actions,
1039 _Thread_queue_Priority_inherit_do_enqueue_change,
1040 queue
1041 );
1042 #endif
1043 }
1044
1045 static void _Thread_queue_Priority_inherit_enqueue(
1046 Thread_queue_Queue *queue,
1047 Thread_Control *the_thread,
1048 Thread_queue_Context *queue_context
1049 )
1050 {
1051 _Thread_queue_Queue_enqueue(
1052 queue,
1053 the_thread,
1054 queue_context,
1055 _Thread_queue_Priority_inherit_do_initialize,
1056 _Thread_queue_Priority_inherit_do_enqueue
1057 );
1058 }
1059
1060 static void _Thread_queue_Priority_inherit_do_extract_action(
1061 Priority_Actions *priority_actions,
1062 void *arg,
1063 Priority_Aggregation *priority_aggregation,
1064 Priority_Action_type priority_action_type
1065 )
1066 {
1067 #if defined(RTEMS_SMP)
1068 Scheduler_Node *scheduler_node_of_owner;
1069
1070 scheduler_node_of_owner = arg;
1071
1072 _Priority_Set_action(
1073 &scheduler_node_of_owner->Wait.Priority,
1074 &priority_aggregation->Node,
1075 priority_action_type
1076 );
1077 _Priority_Actions_add(
1078 priority_actions,
1079 &scheduler_node_of_owner->Wait.Priority
1080 );
1081 #else
1082 Thread_queue_Context *queue_context;
1083 Thread_Control *owner;
1084 Scheduler_Node *scheduler_node_of_owner;
1085
1086 queue_context = THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions );
1087 owner = arg;
1088 scheduler_node_of_owner = _Thread_Scheduler_get_home_node( owner );
1089
1090 _Priority_Actions_initialize_one(
1091 &queue_context->Priority.Actions,
1092 &scheduler_node_of_owner->Wait.Priority,
1093 &priority_aggregation->Node,
1094 priority_action_type
1095 );
1096 _Thread_Priority_perform_actions( arg, queue_context );
1097 #endif
1098 }
1099
1100 static void _Thread_queue_Priority_inherit_do_extract_remove(
1101 Priority_Aggregation *priority_aggregation,
1102 Priority_Actions *priority_actions,
1103 void *arg
1104 )
1105 {
1106 _Thread_queue_Priority_inherit_do_extract_action(
1107 priority_actions,
1108 arg,
1109 priority_aggregation,
1110 PRIORITY_ACTION_REMOVE
1111 );
1112 }
1113
1114 static void _Thread_queue_Priority_inherit_do_extract_change(
1115 Priority_Aggregation *priority_aggregation,
1116 Priority_Group_order priority_group_order,
1117 Priority_Actions *priority_actions,
1118 void *arg
1119 )
1120 {
1121 _Thread_queue_Priority_inherit_do_extract_action(
1122 priority_actions,
1123 arg,
1124 priority_aggregation,
1125 PRIORITY_ACTION_CHANGE
1126 );
1127 }
1128
1129 static void _Thread_queue_Priority_inherit_do_extract(
1130 Thread_queue_Queue *queue,
1131 Thread_queue_Heads *heads,
1132 Thread_Control *owner,
1133 Thread_queue_Context *queue_context,
1134 Thread_Control *the_thread
1135 )
1136 {
1137 #if defined(RTEMS_SMP)
1138 Chain_Node *wait_node;
1139 const Chain_Node *wait_tail;
1140 #endif
1141 Scheduler_Node *scheduler_node;
1142 Thread_queue_Priority_queue *priority_queue;
1143
1144 #if defined(RTEMS_SMP)
1145 wait_node = _Chain_First( &the_thread->Scheduler.Wait_nodes );
1146 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
1147
1148 _Priority_Actions_initialize_empty( &queue_context->Priority.Actions );
1149
1150 do {
1151 size_t scheduler_index;
1152 Scheduler_Node *scheduler_node_of_owner;
1153
1154 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
1155 scheduler_index = _Thread_queue_Scheduler_index( scheduler_node );
1156 priority_queue = _Thread_queue_Priority_queue_by_index(
1157 heads,
1158 scheduler_index
1159 );
1160 scheduler_node_of_owner = _Thread_Scheduler_get_node_by_index(
1161 owner,
1162 scheduler_index
1163 );
1164
1165 _Priority_Extract(
1166 &priority_queue->Queue,
1167 &scheduler_node->Wait.Priority.Node,
1168 &queue_context->Priority.Actions,
1169 _Thread_queue_Priority_inherit_do_extract_remove,
1170 _Thread_queue_Priority_inherit_do_extract_change,
1171 scheduler_node_of_owner
1172 );
1173
1174 if ( _Priority_Is_empty( &priority_queue->Queue ) ) {
1175 _Chain_Extract_unprotected( &priority_queue->Node );
1176 }
1177
1178 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
1179 } while ( wait_node != wait_tail );
1180
1181 if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
1182 _Thread_Priority_perform_actions( owner, queue_context );
1183 }
1184 #else
1185 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
1186 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
1187
1188 _Priority_Extract(
1189 &priority_queue->Queue,
1190 &scheduler_node->Wait.Priority.Node,
1191 &queue_context->Priority.Actions,
1192 _Thread_queue_Priority_inherit_do_extract_remove,
1193 _Thread_queue_Priority_inherit_do_extract_change,
1194 owner
1195 );
1196 #endif
1197 }
1198
1199 static void _Thread_queue_Priority_inherit_extract(
1200 Thread_queue_Queue *queue,
1201 Thread_Control *the_thread,
1202 Thread_queue_Context *queue_context
1203 )
1204 {
1205 #if defined(RTEMS_SMP)
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234 (void) _Thread_queue_Path_acquire( queue, the_thread, queue_context );
1235 #endif
1236
1237 _Thread_queue_Queue_extract(
1238 queue,
1239 queue->heads,
1240 queue->owner,
1241 queue_context,
1242 the_thread,
1243 _Thread_queue_Priority_inherit_do_extract
1244 );
1245
1246 #if defined(RTEMS_SMP)
1247 _Thread_queue_Path_release( queue_context );
1248 #endif
1249 }
1250
1251 #if defined(RTEMS_SMP)
1252 static void _Thread_queue_Priority_inherit_do_surrender_add(
1253 Priority_Aggregation *priority_aggregation,
1254 Priority_Actions *priority_actions,
1255 void *arg
1256 )
1257 {
1258 Scheduler_Node *scheduler_node;
1259 Thread_Control *the_thread;
1260
1261 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
1262 the_thread = arg;
1263
1264 _Thread_Scheduler_add_wait_node( the_thread, scheduler_node );
1265 _Scheduler_Node_set_priority(
1266 scheduler_node,
1267 _Priority_Get_priority( priority_aggregation ),
1268 PRIORITY_GROUP_LAST
1269 );
1270 }
1271
1272 static void _Thread_queue_Priority_inherit_do_surrender_remove(
1273 Priority_Aggregation *priority_aggregation,
1274 Priority_Actions *priority_actions,
1275 void *arg
1276 )
1277 {
1278 Scheduler_Node *scheduler_node;
1279 Thread_Control *the_thread;
1280
1281 scheduler_node = SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation );
1282 the_thread = arg;
1283
1284 _Thread_Scheduler_remove_wait_node( the_thread, scheduler_node );
1285 _Priority_Actions_add( priority_actions, priority_aggregation );
1286 }
1287 #endif
1288
1289 static void _Thread_queue_Priority_inherit_do_surrender_change(
1290 Priority_Aggregation *priority_aggregation,
1291 Priority_Group_order priority_group_order,
1292 Priority_Actions *priority_actions,
1293 void *arg
1294 )
1295 {
1296 #if defined(RTEMS_SMP)
1297 _Priority_Actions_add( priority_actions, priority_aggregation );
1298 #else
1299 _Thread_queue_Context_add_priority_update(
1300 THREAD_QUEUE_CONTEXT_OF_PRIORITY_ACTIONS( priority_actions ),
1301 arg
1302 );
1303 #endif
1304 _Scheduler_Node_set_priority(
1305 SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation ),
1306 _Priority_Get_priority( priority_aggregation ),
1307 priority_group_order
1308 );
1309 }
1310
1311 #if defined(RTEMS_SMP)
1312 static void _Thread_queue_Priority_inherit_do_surrender_change_2(
1313 Priority_Aggregation *priority_aggregation,
1314 Priority_Group_order priority_group_order,
1315 Priority_Actions *priority_actions,
1316 void *arg
1317 )
1318 {
1319 _Scheduler_Node_set_priority(
1320 SCHEDULER_NODE_OF_WAIT_PRIORITY( priority_aggregation ),
1321 _Priority_Get_priority( priority_aggregation ),
1322 priority_group_order
1323 );
1324 }
1325 #endif
1326
1327 static void _Thread_queue_Priority_inherit_do_surrender(
1328 Thread_queue_Queue *queue,
1329 Thread_queue_Heads *heads,
1330 Thread_Control *previous_owner,
1331 Thread_queue_Context *queue_context,
1332 Thread_Control *the_thread
1333 )
1334 {
1335 #if defined(RTEMS_SMP)
1336 Chain_Node *fifo_node;
1337 const Chain_Node *fifo_head;
1338 const Chain_Node *fifo_tail;
1339 Chain_Node *wait_node;
1340 const Chain_Node *wait_tail;
1341 ISR_lock_Context lock_context;
1342 #endif
1343 Scheduler_Node *scheduler_node;
1344 Thread_queue_Priority_queue *priority_queue;
1345 Scheduler_Node *scheduler_node_of_owner;
1346
1347 #if defined(RTEMS_SMP)
1348
1349
1350
1351
1352
1353 fifo_node = _Thread_queue_Priority_queue_rotation( heads );
1354 fifo_head = _Chain_Immutable_head( &heads->Heads.Fifo );
1355
1356 _Priority_Actions_initialize_empty( &queue_context->Priority.Actions );
1357
1358 _Thread_Wait_acquire_default_critical( previous_owner, &lock_context );
1359
1360 do {
1361 priority_queue = (Thread_queue_Priority_queue *) fifo_node;
1362 scheduler_node_of_owner = priority_queue->scheduler_node;
1363
1364 _Assert( scheduler_node_of_owner->owner == previous_owner );
1365
1366 _Priority_Extract(
1367 &scheduler_node_of_owner->Wait.Priority,
1368 &priority_queue->Queue.Node,
1369 &queue_context->Priority.Actions,
1370 _Thread_queue_Priority_inherit_do_surrender_remove,
1371 _Thread_queue_Priority_inherit_do_surrender_change,
1372 previous_owner
1373 );
1374
1375 fifo_node = _Chain_Previous( fifo_node );
1376 } while ( fifo_node != fifo_head );
1377
1378 if ( !_Priority_Actions_is_empty( &queue_context->Priority.Actions ) ) {
1379
1380
1381
1382
1383
1384
1385 _Thread_queue_Context_add_priority_update( queue_context, previous_owner );
1386 #if defined(RTEMS_DEBUG)
1387 _Thread_queue_Do_nothing_priority_actions( queue, &queue_context->Priority.Actions );
1388 #endif
1389 }
1390
1391 _Thread_Wait_release_default_critical( previous_owner, &lock_context );
1392
1393
1394
1395
1396
1397
1398 wait_node = _Chain_First( &the_thread->Scheduler.Wait_nodes );
1399 wait_tail = _Chain_Immutable_tail( &the_thread->Scheduler.Wait_nodes );
1400
1401 do {
1402 scheduler_node = SCHEDULER_NODE_OF_THREAD_WAIT_NODE( wait_node );
1403 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
1404
1405 _Priority_Extract(
1406 &priority_queue->Queue,
1407 &scheduler_node->Wait.Priority.Node,
1408 NULL,
1409 _Thread_queue_Priority_queue_extract,
1410 _Priority_Change_nothing,
1411 NULL
1412 );
1413
1414 wait_node = _Chain_Next( &scheduler_node->Thread.Wait_node );
1415 } while ( wait_node != wait_tail );
1416
1417
1418
1419 fifo_node = _Chain_First( &heads->Heads.Fifo );
1420 fifo_tail = _Chain_Immutable_tail( &heads->Heads.Fifo );
1421
1422 while ( fifo_node != fifo_tail ) {
1423 const Scheduler_Control *scheduler;
1424
1425 priority_queue = (Thread_queue_Priority_queue *) fifo_node;
1426 scheduler = _Priority_Get_scheduler( &priority_queue->Queue );
1427 scheduler_node = _Thread_Scheduler_get_node_by_index(
1428 the_thread,
1429 _Scheduler_Get_index( scheduler )
1430 );
1431
1432 priority_queue->scheduler_node = scheduler_node;
1433 _Priority_Insert(
1434 &scheduler_node->Wait.Priority,
1435 &priority_queue->Queue.Node,
1436 &queue_context->Priority.Actions,
1437 _Thread_queue_Priority_inherit_do_surrender_add,
1438 _Thread_queue_Priority_inherit_do_surrender_change_2,
1439 the_thread
1440 );
1441
1442 fifo_node = _Chain_Next( fifo_node );
1443 }
1444 #else
1445 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
1446 priority_queue = _Thread_queue_Priority_queue( heads, scheduler_node );
1447 scheduler_node_of_owner = priority_queue->scheduler_node;
1448
1449 _Priority_Extract_non_empty(
1450 &scheduler_node_of_owner->Wait.Priority,
1451 &priority_queue->Queue.Node,
1452 &queue_context->Priority.Actions,
1453 _Thread_queue_Priority_inherit_do_surrender_change,
1454 previous_owner
1455 );
1456 _Priority_Extract(
1457 &priority_queue->Queue,
1458 &scheduler_node->Wait.Priority.Node,
1459 NULL,
1460 _Priority_Remove_nothing,
1461 _Priority_Change_nothing,
1462 NULL
1463 );
1464
1465 if ( !_Priority_Is_empty( &priority_queue->Queue ) ) {
1466 priority_queue->scheduler_node = scheduler_node;
1467 _Priority_Non_empty_insert(
1468 &scheduler_node->Wait.Priority,
1469 &priority_queue->Queue.Node,
1470 &queue_context->Priority.Actions,
1471 _Thread_queue_Priority_inherit_do_surrender_change,
1472 the_thread
1473 );
1474 }
1475 #endif
1476 }
1477
1478 static Thread_Control *_Thread_queue_Priority_inherit_surrender(
1479 Thread_queue_Queue *queue,
1480 Thread_queue_Heads *heads,
1481 Thread_Control *previous_owner,
1482 Thread_queue_Context *queue_context
1483 )
1484 {
1485 Thread_Control *first;
1486
1487 first = _Thread_queue_Priority_first( heads );
1488 _Thread_queue_Queue_extract(
1489 queue,
1490 heads,
1491 previous_owner,
1492 queue_context,
1493 first,
1494 _Thread_queue_Priority_inherit_do_surrender
1495 );
1496
1497 return first;
1498 }
1499
1500 const Thread_queue_Operations _Thread_queue_Operations_default = {
1501 .priority_actions = _Thread_queue_Do_nothing_priority_actions
1502
1503
1504
1505
1506
1507 };
1508
1509 const Thread_queue_Operations _Thread_queue_Operations_FIFO = {
1510 .priority_actions = _Thread_queue_Do_nothing_priority_actions,
1511 .enqueue = _Thread_queue_FIFO_enqueue,
1512 .extract = _Thread_queue_FIFO_extract,
1513 .surrender = _Thread_queue_FIFO_surrender,
1514 .first = _Thread_queue_FIFO_first
1515 };
1516
1517 const Thread_queue_Operations _Thread_queue_Operations_priority = {
1518 .priority_actions = _Thread_queue_Priority_priority_actions,
1519 .enqueue = _Thread_queue_Priority_enqueue,
1520 .extract = _Thread_queue_Priority_extract,
1521 .surrender = _Thread_queue_Priority_surrender,
1522 .first = _Thread_queue_Priority_first
1523 };
1524
1525 const Thread_queue_Operations _Thread_queue_Operations_priority_inherit = {
1526 .priority_actions = _Thread_queue_Priority_inherit_priority_actions,
1527 .enqueue = _Thread_queue_Priority_inherit_enqueue,
1528 .extract = _Thread_queue_Priority_inherit_extract,
1529 .surrender = _Thread_queue_Priority_inherit_surrender,
1530 .first = _Thread_queue_Priority_first
1531 };