20 #ifndef _RTEMS_SCORE_SCHEDULERIMPL_H 21 #define _RTEMS_SCORE_SCHEDULERIMPL_H 57 #if defined(RTEMS_SMP) 70 #if defined(RTEMS_SMP) 83 #if defined(RTEMS_SMP) 84 return _Scheduler_Assignments[ cpu_index ].scheduler;
96 uint32_t cpu_index = _Per_CPU_Get_index( cpu );
98 return _Scheduler_Get_by_CPU_index( cpu_index );
105 #if defined(RTEMS_SMP) 112 #if defined(RTEMS_SMP) 151 #if defined(RTEMS_SMP) 155 } Scheduler_Ask_for_help_context ;
163 Scheduler_Ask_for_help_context *help_context = arg;
167 THREAD_RESOURCE_NODE_TO_THREAD( resource_node );
170 next_needs_help = ( *scheduler->
Operations.ask_for_help )(
176 done = next_needs_help != previous_needs_help;
179 help_context->next_needs_help = next_needs_help;
205 needs_help = ( *scheduler->
Operations.ask_for_help )(
211 if ( needs_help != NULL ) {
212 Scheduler_Ask_for_help_context help_context = { needs_help, NULL };
215 &needs_help->Resource_node,
216 _Scheduler_Ask_for_help_visitor,
220 needs_help = help_context.next_needs_help;
222 }
while ( needs_help != NULL );
231 && _Resource_Node_owns_resources( &needs_help->Resource_node )
233 Scheduler_Node *node = _Scheduler_Thread_get_own_node( needs_help );
236 node->help_state != SCHEDULER_HELP_ACTIVE_RIVAL
237 || _Scheduler_Node_get_user( node ) != needs_help
239 _Scheduler_Ask_for_help( needs_help );
256 #if defined(RTEMS_SMP) 263 #if defined(RTEMS_SMP) 264 _Scheduler_Ask_for_help_if_necessary( needs_help );
298 #if defined(RTEMS_SMP) 305 #if defined(RTEMS_SMP) 306 _Scheduler_Ask_for_help_if_necessary( needs_help );
333 #if defined(RTEMS_SMP) 345 #if defined(RTEMS_SMP) 346 _Scheduler_Ask_for_help_if_necessary( needs_help );
457 uint32_t cpu_count = _SMP_Get_processor_count();
460 for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
465 if ( scheduler != NULL && executing != NULL ) {
489 #if defined(RTEMS_SMP) 494 return &_Scheduler_Assignments[ cpu_index ];
498 const Scheduler_Assignment *assignment
501 return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0;
505 const Scheduler_Assignment *assignment
508 return assignment->scheduler != NULL;
517 #if defined(RTEMS_SMP) 518 const Scheduler_Assignment *assignment =
519 _Scheduler_Get_assignment( cpu_index );
521 return assignment->scheduler == scheduler;
535 #if defined(RTEMS_SMP) 538 if ( current_scheduler != scheduler ) {
541 the_thread->
Scheduler.own_control = scheduler;
542 the_thread->
Scheduler.control = scheduler;
552 #if defined(__RTEMS_HAVE_SYS_CPUSET_H__) 560 uint32_t cpu_count = _SMP_Get_processor_count();
563 CPU_ZERO_S( cpusetsize, cpuset );
565 for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
566 #if defined(RTEMS_SMP) 567 if ( _Scheduler_Has_processor_ownership( scheduler, cpu_index ) ) {
568 CPU_SET_S( (
int) cpu_index, cpusetsize, cpuset );
573 CPU_SET_S( (
int) cpu_index, cpusetsize, cpuset );
587 _Scheduler_Get_processor_set( scheduler, cpusetsize, cpuset );
592 bool _Scheduler_Get_affinity(
602 const cpu_set_t *cpuset
605 uint32_t cpu_count = _SMP_Get_processor_count();
609 for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
610 #if defined(RTEMS_SMP) 612 _Scheduler_Get_by_CPU_index( cpu_index );
615 && ( CPU_ISSET_S( (
int) cpu_index, cpusetsize, cpuset )
616 || ( !CPU_ISSET_S( (
int) cpu_index, cpusetsize, cpuset )
617 && scheduler != scheduler_of_cpu ) );
621 ok = ok && CPU_ISSET_S( (
int) cpu_index, cpusetsize, cpuset );
628 bool _Scheduler_Set_affinity(
631 const cpu_set_t *cpuset
643 if ( heir != new_heir && ( heir->
is_preemptible || force_dispatch ) ) {
644 _Thread_Heir = new_heir;
645 _Thread_Dispatch_necessary =
true;
661 ( *extract )( scheduler, the_thread );
666 ( *schedule )( scheduler, the_thread, true );
700 #if defined(RTEMS_SMP) 701 return _Scheduler_Get_context( scheduler )->processor_count;
712 OBJECTS_FAKE_OBJECTS_API,
713 OBJECTS_FAKE_OBJECTS_SCHEDULERS,
721 uint32_t minimum_id = _Scheduler_Build_id( 0 );
723 return id - minimum_id;
731 uint32_t index = _Scheduler_Get_index_by_id(
id );
734 *scheduler_p = scheduler;
737 && _Scheduler_Get_processor_count( scheduler ) > 0;
743 bool ok = _Scheduler_Get_by_id(
id, &scheduler );
769 #if defined(RTEMS_SMP) 770 node->user = the_thread;
771 node->help_state = SCHEDULER_HELP_YOURSELF;
772 node->owner = the_thread;
774 node->accepts_help = the_thread;
781 #if defined(RTEMS_SMP) 800 typedef void ( *Scheduler_Release_idle_thread )(
842 _Scheduler_Get_own( previous_user_of_node );
844 the_thread->
Scheduler.control = scheduler;
845 _Scheduler_Thread_set_node( the_thread, node );
848 extern const bool _Scheduler_Thread_state_valid_state_changes[ 3 ][ 3 ];
852 Thread_Scheduler_state new_state
856 _Scheduler_Thread_state_valid_state_changes
857 [ the_thread->
Scheduler.state ][ new_state ]
873 Scheduler_Help_state new_help_state
876 Scheduler_Node *node = _Scheduler_Thread_get_own_node( the_thread );
877 Scheduler_Help_state previous_help_state = node->help_state;
879 node->help_state = new_help_state;
881 return previous_help_state;
900 void _Scheduler_Thread_change_resource_root(
911 node->help_state == SCHEDULER_HELP_ACTIVE_OWNER
912 || node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL
914 _Assert( _Scheduler_Node_get_idle( node ) == NULL );
916 _Scheduler_Node_get_owner( node ) == _Scheduler_Node_get_user( node )
919 _Scheduler_Thread_set_node( idle, node );
921 _Scheduler_Node_set_user( node, idle );
940 Scheduler_Get_idle_thread get_idle_thread
945 _Scheduler_Set_idle_thread( node, idle );
951 SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE,
952 SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE,
953 SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK
954 } Scheduler_Try_to_schedule_action;
968 _Scheduler_Try_to_schedule_node(
972 Scheduler_Get_idle_thread get_idle_thread
975 Scheduler_Try_to_schedule_action action;
979 action = SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE;
981 if ( node->help_state == SCHEDULER_HELP_YOURSELF ) {
985 owner = _Scheduler_Node_get_owner( node );
986 user = _Scheduler_Node_get_user( node );
988 if ( node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL) {
989 if ( user->
Scheduler.state == THREAD_SCHEDULER_READY ) {
990 _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
991 }
else if ( owner->
Scheduler.state == THREAD_SCHEDULER_BLOCKED ) {
992 if ( idle != NULL ) {
993 action = SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE;
995 _Scheduler_Use_idle_thread( context, node, get_idle_thread );
998 _Scheduler_Node_set_user( node, owner );
1000 }
else if ( node->help_state == SCHEDULER_HELP_ACTIVE_OWNER ) {
1001 if ( user->
Scheduler.state == THREAD_SCHEDULER_READY ) {
1002 _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
1003 }
else if ( idle != NULL ) {
1004 action = SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE;
1006 _Scheduler_Use_idle_thread( context, node, get_idle_thread );
1009 _Assert( node->help_state == SCHEDULER_HELP_PASSIVE );
1011 if ( user->
Scheduler.state == THREAD_SCHEDULER_READY ) {
1012 _Scheduler_Thread_set_scheduler_and_node( user, node, owner );
1014 action = SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK;
1034 Scheduler_Release_idle_thread release_idle_thread
1039 if ( idle != NULL ) {
1043 _Scheduler_Node_set_user( node, owner );
1044 _Scheduler_Thread_change_state( idle, THREAD_SCHEDULER_READY );
1045 _Scheduler_Thread_set_node( idle, idle->
Scheduler.own_node );
1047 ( *release_idle_thread )( context, idle );
1059 uses_idle->idle = NULL;
1060 _Scheduler_Node_set_user(
1062 _Scheduler_Node_get_owner( uses_idle )
1064 _Scheduler_Set_idle_thread( needs_idle, idle );
1086 Scheduler_Get_idle_thread get_idle_thread
1092 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_BLOCKED );
1094 if ( node->help_state == SCHEDULER_HELP_YOURSELF ) {
1095 _Assert( thread == _Scheduler_Node_get_user( node ) );
1102 if ( node->help_state == SCHEDULER_HELP_ACTIVE_OWNER ) {
1103 if ( is_scheduled ) {
1104 _Assert( thread == _Scheduler_Node_get_user( node ) );
1106 new_user = _Scheduler_Use_idle_thread( context, node, get_idle_thread );
1108 }
else if ( node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL ) {
1109 if ( is_scheduled ) {
1110 old_user = _Scheduler_Node_get_user( node );
1112 if ( thread == old_user ) {
1117 && owner->
Scheduler.state == THREAD_SCHEDULER_READY
1120 _Scheduler_Node_set_user( node, new_user );
1122 new_user = _Scheduler_Use_idle_thread( context, node, get_idle_thread );
1131 if ( new_user != NULL ) {
1134 _Scheduler_Thread_change_state( new_user, THREAD_SCHEDULER_SCHEDULED );
1135 _Thread_Set_CPU( new_user, cpu );
1136 _Thread_Dispatch_update_heir( _Per_CPU_Get(), cpu, new_user );
1159 Scheduler_Release_idle_thread release_idle_thread
1164 if ( is_scheduled ) {
1175 if ( node->help_state == SCHEDULER_HELP_ACTIVE_OWNER ) {
1177 new_user = the_thread;
1178 }
else if ( idle != NULL ) {
1179 _Assert( node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL );
1180 new_user = the_thread;
1181 }
else if ( the_thread != owner ) {
1182 _Assert( node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL );
1183 _Assert( old_user != the_thread );
1184 _Scheduler_Thread_change_state( owner, THREAD_SCHEDULER_READY );
1185 new_user = the_thread;
1186 _Scheduler_Node_set_user( node, new_user );
1188 _Assert( node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL );
1189 _Assert( old_user != the_thread );
1190 _Scheduler_Thread_change_state( the_thread, THREAD_SCHEDULER_READY );
1194 if ( new_user != NULL ) {
1195 _Scheduler_Thread_change_state( new_user, THREAD_SCHEDULER_SCHEDULED );
1196 _Thread_Set_CPU( new_user, cpu );
1197 _Thread_Dispatch_update_heir( _Per_CPU_Get(), cpu, new_user );
1202 _Scheduler_Thread_change_state( the_thread, THREAD_SCHEDULER_READY );
1223 _Scheduler_Node_set_user( node, needs_help );
1249 Scheduler_Release_idle_thread release_idle_thread
1257 previous_accepts_help != needs_help
1258 && _Scheduler_Thread_get_node( previous_accepts_help ) == node
1266 if ( idle != NULL ) {
1269 _Assert( _Scheduler_Node_get_user( node ) == previous_accepts_help );
1270 old_user = previous_accepts_help;
1273 if ( needs_help->
Scheduler.state == THREAD_SCHEDULER_READY ) {
1274 new_user = needs_help;
1277 node->help_state == SCHEDULER_HELP_ACTIVE_OWNER
1278 || node->help_state == SCHEDULER_HELP_ACTIVE_RIVAL
1282 new_user = offers_help;
1285 if ( previous_accepts_help != offers_help ) {
1286 next_needs_help = previous_accepts_help;
1288 }
else if ( needs_help->
Scheduler.state == THREAD_SCHEDULER_READY ) {
1295 if ( idle != NULL ) {
1298 old_user = _Scheduler_Node_get_user( node );
1301 new_user = needs_help;
1306 if ( new_user != old_user ) {
1310 _Scheduler_Thread_change_state( old_user, THREAD_SCHEDULER_READY );
1311 _Scheduler_Thread_set_scheduler_and_node(
1313 _Scheduler_Thread_get_own_node( old_user ),
1317 _Scheduler_Thread_change_state( new_user, THREAD_SCHEDULER_SCHEDULED );
1318 _Scheduler_Thread_set_scheduler_and_node( new_user, node, offers_help );
1320 _Scheduler_Node_set_user( node, new_user );
1321 _Thread_Set_CPU( new_user, cpu );
1322 _Thread_Dispatch_update_heir( cpu_self, cpu, new_user );
1325 return next_needs_help;
1348 _Assert( node->help_state == SCHEDULER_HELP_PASSIVE );
1350 if ( needs_help->
Scheduler.state == THREAD_SCHEDULER_READY ) {
1351 _Scheduler_Node_set_user( node, needs_help );
1352 _Scheduler_Thread_set_scheduler_and_node( needs_help, node, offers_help );
RTEMS_INLINE_ROUTINE void _Scheduler_Block(Thread_Control *the_thread)
Blocks a thread with respect to the scheduler.
Definition: schedulerimpl.h:278
RTEMS_INLINE_ROUTINE bool _Scheduler_Is_priority_higher_than(const Scheduler_Control *scheduler, Priority_Control p1, Priority_Control p2)
Returns true if p1 encodes a higher priority than p2 in the intuitive sense of priority.
Definition: schedulerimpl.h:687
RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(Thread_Control *the_thread, uint32_t length)
Releases a job of a thread with respect to the scheduler.
Definition: schedulerimpl.h:437
Scheduler_Void_or_thread(* change_priority)(const Scheduler_Control *, Thread_Control *, Priority_Control, bool)
Definition: scheduler.h:87
Scheduler control.
Definition: scheduler.h:192
Priority_Control current_priority
This field is the current priority state of this thread.
Definition: thread.h:683
Scheduler_Operations Operations
The scheduler operations.
Definition: scheduler.h:201
Scheduler context.
Definition: scheduler.h:180
#define _ISR_lock_ISR_disable_and_acquire(_lock, _context)
Acquires an ISR lock.
Definition: isrlock.h:205
Scheduler_Context * context
Reference to a statically allocated scheduler context.
Definition: scheduler.h:196
#define RTEMS_INLINE_ROUTINE
The following (in conjunction with compiler arguments) are used to choose between the use of static i...
Definition: basedefs.h:135
RTEMS_INLINE_ROUTINE void _Scheduler_Acquire(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Acquires the scheduler instance of the thread.
Definition: schedulerimpl.h:1371
RTEMS_INLINE_ROUTINE bool _Thread_Is_executing(const Thread_Control *the_thread)
This function returns true if the_thread is the currently executing thread, and false otherwise...
Definition: threadimpl.h:517
RTEMS_INLINE_ROUTINE void _Scheduler_Unblock(Thread_Control *the_thread)
Unblocks a thread with respect to the scheduler.
Definition: schedulerimpl.h:295
#define ISR_LOCK_DECLARE(_qualifier, _designator)
Declares an ISR lock variable.
Definition: isrlock.h:104
void(* release_job)(const Scheduler_Control *, Thread_Control *, uint32_t)
Definition: scheduler.h:139
void(* node_initialize)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:120
RTEMS_INLINE_ROUTINE void _Scheduler_Schedule(Thread_Control *the_thread)
The preferred method to add a new scheduler is to define the jump table entries and add a case to the...
Definition: schedulerimpl.h:144
RTEMS_INLINE_ROUTINE Objects_Id _Objects_Build_id(Objects_APIs the_api, uint16_t the_class, uint8_t node, uint16_t index)
This function builds an object's id from the processor node and index values specified.
Definition: object.h:397
Resource node to reflect ownership of resources and a dependency on a resource.
Definition: resource.h:150
void(* block)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:75
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
States_Control _Thread_Set_state(Thread_Control *the_thread, States_Control state)
Sets the specified thread state.
Definition: threadsetstate.c:28
void(* tick)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:146
RTEMS_INLINE_ROUTINE bool _Thread_Is_heir(const Thread_Control *the_thread)
This function returns true if the_thread is the heir thread, and false otherwise. ...
Definition: threadimpl.h:575
RTEMS_INLINE_ROUTINE void _Scheduler_Start_idle(const Scheduler_Control *scheduler, Thread_Control *the_thread, Per_CPU_Control *cpu)
Starts the idle thread for a particular processor.
Definition: schedulerimpl.h:480
struct Scheduler_Node * node
The scheduler node of this thread.
Definition: thread.h:609
This structure defines the Thread Control Block (TCB).
Definition: thread.h:671
Per CPU Core Structure.
Definition: percpu.h:233
RTEMS_INLINE_ROUTINE void _Scheduler_Release(Thread_Control *the_thread, ISR_lock_Context *lock_context)
Releases the scheduler instance of the thread.
Definition: schedulerimpl.h:1386
int(* priority_compare)(Priority_Control, Priority_Control)
Definition: scheduler.h:133
Implementation Helper for CPU Set.
Constants and Structures Associated with the Scheduler.
void(* schedule)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:66
#define _ISR_lock_Release_and_ISR_enable(_lock, _context)
Releases an ISR lock.
Definition: isrlock.h:230
void(* node_destroy)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:123
#define _Assert(_e)
Assertion similar to assert() controlled via RTEMS_DEBUG instead of NDEBUG.
Definition: assert.h:83
void _Resource_Iterate(Resource_Node *top, Resource_Node_visitor visitor, void *arg)
Iterates over all nodes of a resource dependency tree.
Definition: resourceiterate.c:28
RTEMS_INLINE_ROUTINE void _Scheduler_Node_initialize(const Scheduler_Control *scheduler, Thread_Control *the_thread)
Initializes a scheduler node.
Definition: schedulerimpl.h:361
void(* update_priority)(const Scheduler_Control *, Thread_Control *, Priority_Control)
Definition: scheduler.h:126
struct Thread_Control * executing
This is the thread executing on this processor.
Definition: percpu.h:278
RTEMS_INLINE_ROUTINE int _Scheduler_Priority_compare(const Scheduler_Control *scheduler, Priority_Control p1, Priority_Control p2)
Compares two priority values.
Definition: schedulerimpl.h:422
Scheduler_Void_or_thread(* yield)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:69
#define STATES_MIGRATING
This macro corresponds to a task migrating to another scheduler.
Definition: statesimpl.h:84
RTEMS_INLINE_ROUTINE void _Scheduler_Update_priority(Thread_Control *the_thread, Priority_Control new_priority)
Updates the scheduler about a priority change of a not ready thread.
Definition: schedulerimpl.h:392
RTEMS_INLINE_ROUTINE void _Scheduler_Node_destroy(const Scheduler_Control *scheduler, Thread_Control *the_thread)
Destroys a scheduler node.
Definition: schedulerimpl.h:378
RTEMS_INLINE_ROUTINE bool _Scheduler_Is_priority_lower_than(const Scheduler_Control *scheduler, Priority_Control p1, Priority_Control p2)
Returns true if p1 encodes a lower priority than p2 in the intuitive sense of priority.
Definition: schedulerimpl.h:674
Scheduler node for per-thread data.
Definition: scheduler.h:281
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
Scheduler_Void_or_thread(* unblock)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:81
Inlined Routines from the Thread Handler.
RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority(Thread_Control *the_thread, Priority_Control new_priority, bool prepend_it)
Propagates a priority change of a thread to the scheduler.
Definition: schedulerimpl.h:326
void(* start_idle)(const Scheduler_Control *, Thread_Control *, struct Per_CPU_Control *)
Definition: scheduler.h:149
RTEMS_INLINE_ROUTINE void _Scheduler_Yield(Thread_Control *the_thread)
Scheduler yield with a particular thread.
Definition: schedulerimpl.h:253
States_Control _Thread_Clear_state(Thread_Control *the_thread, States_Control state)
Clears the specified thread state.
Definition: threadclearstate.c:25
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
uint32_t Objects_Id
The following type defines the control block used to manage object IDs.
Definition: object.h:122
void _Scheduler_Handler_initialization(void)
Initializes the scheduler to the policy chosen by the user.
Definition: scheduler.c:25
#define _Objects_Local_node
The following is referenced to the node number of the local node.
Definition: objectimpl.h:183
bool is_preemptible
This field is true if the thread is preemptible.
Definition: thread.h:749
SuperCore SMP Implementation.
RTEMS_INLINE_ROUTINE void _Scheduler_Tick(void)
Scheduler method invoked at each clock tick.
Definition: schedulerimpl.h:455
#define _Scheduler_Count
Count of registered schedulers.
Definition: scheduler.h:352