23 #ifndef _RTEMS_SCORE_SCHEDULERSMPIMPL_H 24 #define _RTEMS_SCORE_SCHEDULERSMPIMPL_H 288 typedef void ( *Scheduler_SMP_Extract )(
293 typedef void ( *Scheduler_SMP_Insert )(
298 typedef void ( *Scheduler_SMP_Move )(
303 typedef void ( *Scheduler_SMP_Update )(
320 typedef void ( *Scheduler_SMP_Allocate_processor )(
326 static inline bool _Scheduler_SMP_Insert_priority_lifo_order(
339 static inline bool _Scheduler_SMP_Insert_priority_fifo_order(
359 static inline void _Scheduler_SMP_Initialize(
388 static inline void _Scheduler_SMP_Node_initialize(
393 _Scheduler_Node_do_initialize( &node->
Base, thread );
397 static inline void _Scheduler_SMP_Node_update_priority(
405 extern const bool _Scheduler_SMP_Node_valid_state_changes[ 3 ][ 3 ];
407 static inline void _Scheduler_SMP_Node_change_state(
413 _Scheduler_SMP_Node_valid_state_changes[ node->
state ][ new_state ]
416 node->
state = new_state;
419 static inline bool _Scheduler_SMP_Is_processor_owned_by_us(
424 return cpu->scheduler_context == context;
440 static inline void _Scheduler_SMP_Release_idle_thread(
450 static inline void _Scheduler_SMP_Allocate_processor_lazy(
463 if ( _Thread_Is_executing_on_a_processor( scheduled_thread ) ) {
464 if ( _Scheduler_SMP_Is_processor_owned_by_us( context, scheduled_cpu ) ) {
465 heir = scheduled_cpu->
heir;
466 _Thread_Dispatch_update_heir(
474 scheduled_thread->
Scheduler.debug_real_cpu->heir != scheduled_thread
476 heir = scheduled_thread;
479 heir = scheduled_thread;
482 if ( heir != victim_thread ) {
483 _Thread_Set_CPU( heir, victim_cpu );
484 _Thread_Dispatch_update_heir( cpu_self, victim_cpu, heir );
488 static inline void _Scheduler_SMP_Allocate_processor(
492 Scheduler_SMP_Allocate_processor allocate_processor
495 Thread_Control *scheduled_thread = _Scheduler_Node_get_user( scheduled );
496 Thread_Control *victim_thread = _Scheduler_Node_get_user( victim );
498 _Scheduler_SMP_Node_change_state(
499 _Scheduler_SMP_Node_downcast( scheduled ),
502 _Scheduler_Thread_change_state( scheduled_thread, THREAD_SCHEDULER_SCHEDULED );
504 ( *allocate_processor )( context, scheduled_thread, victim_thread );
507 static inline Scheduler_Node *_Scheduler_SMP_Get_lowest_scheduled(
523 return lowest_scheduled;
526 static inline Thread_Control *_Scheduler_SMP_Enqueue_to_scheduled(
530 Scheduler_SMP_Insert insert_scheduled,
531 Scheduler_SMP_Move move_from_scheduled_to_ready,
532 Scheduler_SMP_Allocate_processor allocate_processor
536 Scheduler_Try_to_schedule_action action;
538 action = _Scheduler_Try_to_schedule_node(
541 _Scheduler_Node_get_idle( lowest_scheduled ),
542 _Scheduler_SMP_Get_idle_thread
545 if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
547 _Scheduler_Node_get_user( lowest_scheduled );
550 _Scheduler_SMP_Node_change_state(
551 _Scheduler_SMP_Node_downcast( lowest_scheduled ),
554 _Scheduler_Thread_change_state(
555 lowest_scheduled_user,
556 THREAD_SCHEDULER_READY
559 _Scheduler_SMP_Allocate_processor(
566 ( *insert_scheduled )( context, node );
567 ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
569 idle = _Scheduler_Release_idle_thread(
572 _Scheduler_SMP_Release_idle_thread
574 if ( idle == NULL ) {
575 needs_help = lowest_scheduled_user;
579 }
else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
580 _Scheduler_SMP_Node_change_state(
581 _Scheduler_SMP_Node_downcast( lowest_scheduled ),
584 _Scheduler_SMP_Node_change_state(
585 _Scheduler_SMP_Node_downcast( node ),
589 ( *insert_scheduled )( context, node );
590 ( *move_from_scheduled_to_ready )( context, lowest_scheduled );
592 _Scheduler_Exchange_idle_thread(
595 _Scheduler_Node_get_idle( lowest_scheduled )
600 _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
601 _Scheduler_SMP_Node_change_state(
602 _Scheduler_SMP_Node_downcast( node ),
639 Scheduler_SMP_Insert insert_ready,
640 Scheduler_SMP_Insert insert_scheduled,
641 Scheduler_SMP_Move move_from_scheduled_to_ready,
642 Scheduler_SMP_Get_lowest_scheduled get_lowest_scheduled,
643 Scheduler_SMP_Allocate_processor allocate_processor
647 ( *get_lowest_scheduled )( context, node, order );
649 if ( ( *order )( &node->Node, &lowest_scheduled->Node ) ) {
650 needs_help = _Scheduler_SMP_Enqueue_to_scheduled(
655 move_from_scheduled_to_ready,
659 ( *insert_ready )( context, node );
684 static inline Thread_Control *_Scheduler_SMP_Enqueue_scheduled_ordered(
688 Scheduler_SMP_Extract extract_from_ready,
689 Scheduler_SMP_Get_highest_ready get_highest_ready,
690 Scheduler_SMP_Insert insert_ready,
691 Scheduler_SMP_Insert insert_scheduled,
692 Scheduler_SMP_Move move_from_ready_to_scheduled,
693 Scheduler_SMP_Allocate_processor allocate_processor
699 Scheduler_Node *highest_ready = ( *get_highest_ready )( context, node );
705 if ( ( *order )( &node->Node, &highest_ready->Node ) ) {
706 ( *insert_scheduled )( context, node );
710 Scheduler_Try_to_schedule_action action;
712 action = _Scheduler_Try_to_schedule_node(
715 _Scheduler_Node_get_idle( node ),
716 _Scheduler_SMP_Get_idle_thread
719 if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
723 _Scheduler_SMP_Node_change_state(
724 _Scheduler_SMP_Node_downcast( node ),
727 _Scheduler_Thread_change_state( user, THREAD_SCHEDULER_READY );
729 _Scheduler_SMP_Allocate_processor(
736 ( *insert_ready )( context, node );
737 ( *move_from_ready_to_scheduled )( context, highest_ready );
739 idle = _Scheduler_Release_idle_thread(
742 _Scheduler_SMP_Release_idle_thread
744 if ( idle == NULL ) {
749 }
else if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE ) {
750 _Scheduler_SMP_Node_change_state(
751 _Scheduler_SMP_Node_downcast( node ),
754 _Scheduler_SMP_Node_change_state(
755 _Scheduler_SMP_Node_downcast( highest_ready ),
759 ( *insert_ready )( context, node );
760 ( *move_from_ready_to_scheduled )( context, highest_ready );
762 _Scheduler_Exchange_idle_thread(
765 _Scheduler_Node_get_idle( node )
770 _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
772 _Scheduler_SMP_Node_change_state(
773 _Scheduler_SMP_Node_downcast( highest_ready ),
777 ( *extract_from_ready )( context, highest_ready );
787 static inline void _Scheduler_SMP_Extract_from_scheduled(
794 static inline void _Scheduler_SMP_Schedule_highest_ready(
797 Scheduler_SMP_Extract extract_from_ready,
798 Scheduler_SMP_Get_highest_ready get_highest_ready,
799 Scheduler_SMP_Move move_from_ready_to_scheduled,
800 Scheduler_SMP_Allocate_processor allocate_processor
804 Scheduler_Node *highest_ready = ( *get_highest_ready )( context, victim );
805 Scheduler_Try_to_schedule_action action;
807 action = _Scheduler_Try_to_schedule_node(
811 _Scheduler_SMP_Get_idle_thread
814 if ( action == SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE ) {
815 _Scheduler_SMP_Allocate_processor(
822 ( *move_from_ready_to_scheduled )( context, highest_ready );
824 _Assert( action == SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK );
826 _Scheduler_SMP_Node_change_state(
827 _Scheduler_SMP_Node_downcast( highest_ready ),
831 ( *extract_from_ready )( context, highest_ready );
849 static inline void _Scheduler_SMP_Block(
852 Scheduler_SMP_Extract extract_from_ready,
853 Scheduler_SMP_Get_highest_ready get_highest_ready,
854 Scheduler_SMP_Move move_from_ready_to_scheduled,
855 Scheduler_SMP_Allocate_processor allocate_processor
864 block = _Scheduler_Block_node(
869 _Scheduler_SMP_Get_idle_thread
874 if ( is_scheduled ) {
875 _Scheduler_SMP_Extract_from_scheduled( &node->
Base );
877 _Scheduler_SMP_Schedule_highest_ready(
882 move_from_ready_to_scheduled,
886 ( *extract_from_ready )( context, &node->
Base );
894 Scheduler_SMP_Enqueue enqueue_fifo
899 bool unblock = _Scheduler_Unblock_node(
904 _Scheduler_SMP_Release_idle_thread
912 needs_help = ( *enqueue_fifo )( context, &node->
Base, thread );
916 node->
Base.help_state == SCHEDULER_HELP_ACTIVE_OWNER
917 || node->
Base.help_state == SCHEDULER_HELP_ACTIVE_RIVAL
921 if ( node->
Base.accepts_help == thread ) {
939 Scheduler_SMP_Extract extract_from_ready,
940 Scheduler_SMP_Update update,
941 Scheduler_SMP_Enqueue enqueue_fifo,
942 Scheduler_SMP_Enqueue enqueue_lifo,
943 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled_fifo,
944 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled_lifo
951 _Scheduler_SMP_Extract_from_scheduled( &node->
Base );
953 ( *update )( context, &node->
Base, new_priority );
956 needs_help = ( *enqueue_scheduled_lifo )( context, &node->
Base );
958 needs_help = ( *enqueue_scheduled_fifo )( context, &node->
Base );
961 ( *extract_from_ready )( context, &node->
Base );
963 ( *update )( context, &node->
Base, new_priority );
966 needs_help = ( *enqueue_lifo )( context, &node->
Base, NULL );
968 needs_help = ( *enqueue_fifo )( context, &node->
Base, NULL );
971 ( *update )( context, &node->
Base, new_priority );
983 Scheduler_SMP_Enqueue enqueue_fifo
990 previous_accepts_help = node->
Base.accepts_help;
991 node->
Base.accepts_help = needs_help;
993 switch ( node->
state ) {
996 _Scheduler_Ask_ready_node_for_help( &node->
Base, needs_help );
999 next_needs_help = _Scheduler_Ask_scheduled_node_for_help(
1004 previous_accepts_help,
1005 _Scheduler_SMP_Release_idle_thread
1010 _Scheduler_Ask_blocked_node_for_help(
1019 next_needs_help = ( *enqueue_fifo )(
1028 return next_needs_help;
1034 Scheduler_SMP_Extract extract_from_ready,
1035 Scheduler_SMP_Enqueue enqueue_fifo,
1036 Scheduler_SMP_Enqueue_scheduled enqueue_scheduled_fifo
1043 _Scheduler_SMP_Extract_from_scheduled( &node->
Base );
1045 needs_help = ( *enqueue_scheduled_fifo )( context, &node->
Base );
1047 ( *extract_from_ready )( context, &node->
Base );
1049 needs_help = ( *enqueue_fifo )( context, &node->
Base, NULL );
1055 static inline void _Scheduler_SMP_Insert_scheduled_lifo(
1064 &node_to_insert->Node,
1065 _Scheduler_SMP_Insert_priority_lifo_order
1069 static inline void _Scheduler_SMP_Insert_scheduled_fifo(
1078 &node_to_insert->Node,
1079 _Scheduler_SMP_Insert_priority_fifo_order
Scheduler context specialization for SMP schedulers.
Definition: schedulersmp.h:44
This is used to manage each element (node) which is placed on a chain.
Definition: chain.h:65
Inlined Routines Associated with the Manipulation of the Priority-Based Scheduling Structures...
This scheduler node is blocked.
Definition: schedulersmp.h:74
Scheduler context.
Definition: scheduler.h:180
struct Thread_Control * heir
This is the heir thread for this processor.
Definition: percpu.h:292
Priority_Control priority
The current priority of thread owning this node.
Definition: schedulersmp.h:112
This is used to manage a chain.
Definition: chain.h:83
RTEMS_INLINE_ROUTINE void _Chain_Extract_unprotected(Chain_Node *the_node)
Extract this node (unprotected).
Definition: chainimpl.h:639
bool(* Chain_Node_order)(const Chain_Node *left, const Chain_Node *right)
Chain node order.
Definition: chainimpl.h:918
#define _ISR_Get_level()
Return current interrupt level.
Definition: isrlevel.h:120
RTEMS_INLINE_ROUTINE void _Chain_Initialize_empty(Chain_Control *the_chain)
Initialize this chain as empty.
Definition: chainimpl.h:613
Scheduler_SMP_Node_state state
The state of this node.
Definition: schedulersmp.h:107
uint32_t Priority_Control
The following type defines the control block used to manage thread priorities.
Definition: priority.h:56
Thread_Scheduler_control Scheduler
Scheduler related control.
Definition: thread.h:756
Objects_Control Object
This field is the object management structure for each thread.
Definition: thread.h:673
This structure defines the Thread Control Block (TCB).
Definition: thread.h:671
Per CPU Core Structure.
Definition: percpu.h:233
Chain_Node Node
This is the chain node portion of an object.
Definition: object.h:234
RTEMS_INLINE_ROUTINE Chain_Node * _Chain_Last(Chain_Control *the_chain)
Return pointer to chain's last node.
Definition: chainimpl.h:400
This scheduler node is ready.
Definition: schedulersmp.h:92
The scheduler node is scheduled.
Definition: schedulersmp.h:84
Scheduler node specialization for SMP schedulers.
Definition: schedulersmp.h:98
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG.
Definition: assert.h:83
RTEMS_INLINE_ROUTINE Chain_Node * _Chain_Tail(Chain_Control *the_chain)
Return pointer to chain tail.
Definition: chainimpl.h:333
Scheduler_Node Base
Basic scheduler node.
Definition: schedulersmp.h:102
Scheduler node for per-thread data.
Definition: scheduler.h:281
RTEMS_INLINE_ROUTINE Chain_Node * _Chain_Get_first_unprotected(Chain_Control *the_chain)
Get the first node (unprotected).
Definition: chainimpl.h:667
RTEMS_INLINE_ROUTINE void _Chain_Insert_ordered_unprotected(Chain_Control *chain, Chain_Node *to_insert, Chain_Node_order order)
Inserts a node into the chain according to the order relation.
Definition: chainimpl.h:934
RTEMS_INLINE_ROUTINE void _Chain_Prepend_unprotected(Chain_Control *the_chain, Chain_Node *the_node)
Prepend a node (unprotected).
Definition: chainimpl.h:787
Scheduler_SMP_Node_state
SMP scheduler node states.
Definition: schedulersmp.h:68