20 #ifndef _RTEMS_SCORE_SCHEDULERIMPL_H 21 #define _RTEMS_SCORE_SCHEDULERIMPL_H 24 #include <rtems/score/assert.h> 25 #include <rtems/score/priorityimpl.h> 27 #include <rtems/score/status.h> 42 #define SCHEDULER_PRIORITY_MAP( priority ) ( ( priority ) << 1 ) 47 #define SCHEDULER_PRIORITY_UNMAP( priority ) ( ( priority ) >> 1 ) 52 #define SCHEDULER_PRIORITY_PURIFY( priority ) \ 53 ( ( priority ) & ~( (Priority_Control) SCHEDULER_PRIORITY_APPEND_FLAG ) ) 58 #define SCHEDULER_PRIORITY_APPEND( priority ) \ 59 ( ( priority ) | SCHEDULER_PRIORITY_APPEND_FLAG ) 66 #define SCHEDULER_PRIORITY_IS_APPEND( priority ) \ 67 ( ( ( priority ) & SCHEDULER_PRIORITY_APPEND_FLAG ) != 0 ) 89 #if defined(RTEMS_SMP) 90 return cpu->Scheduler.control;
110 #if defined(RTEMS_SMP) 113 context = _Scheduler_Get_context( scheduler );
134 #if defined(RTEMS_SMP) 137 context = _Scheduler_Get_context( scheduler );
145 #if defined(RTEMS_SMP) 146 void _Scheduler_Request_ask_for_help(
Thread_Control *the_thread );
161 _Assert( _Thread_State_is_owner( the_thread ) );
163 if ( the_thread->
Scheduler.helping_nodes > 0 ) {
164 _Scheduler_Request_ask_for_help( the_thread );
197 scheduler = _Thread_Scheduler_get_home( the_thread );
218 scheduler = _Thread_Scheduler_get_home( the_thread );
223 _Thread_Scheduler_get_home_node( the_thread )
240 #if defined(RTEMS_SMP) 250 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
251 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
263 while ( node != tail ) {
264 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
265 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
272 THREAD_SCHEDULER_BLOCKED
281 scheduler = _Thread_Scheduler_get_home( the_thread );
285 _Thread_Scheduler_get_home_node( the_thread )
306 #if defined(RTEMS_SMP) 307 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE(
310 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
312 scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
313 scheduler = _Thread_Scheduler_get_home( the_thread );
337 #if defined(RTEMS_SMP) 341 _Thread_Scheduler_process_requests( the_thread );
351 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
352 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
363 }
while ( node != tail );
367 scheduler = _Thread_Scheduler_get_home( the_thread );
371 _Thread_Scheduler_get_home_node( the_thread )
376 #if defined(RTEMS_SMP) 387 int sticky_level_change
396 _Thread_Scheduler_process_requests( the_thread );
399 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
400 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
404 scheduler_node->sticky_level += sticky_level_change;
405 _Assert( scheduler_node->sticky_level >= 0 );
418 while ( node != tail ) {
419 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
420 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
535 _Thread_queue_Context_clear_priority_updates( queue_context );
561 _Thread_queue_Context_clear_priority_updates( queue_context );
583 if ( scheduler !=
NULL && executing !=
NULL ) {
611 #if defined(RTEMS_SMP) 615 cpu = _Per_CPU_Get_by_index( cpu_index );
616 scheduler_of_cpu = _Scheduler_Get_by_CPU( cpu );
618 return scheduler_of_cpu == scheduler;
631 #if defined(RTEMS_SMP) 632 return &_Scheduler_Get_context( scheduler )->Processors;
634 return &_Processor_mask_The_one_and_only;
638 bool _Scheduler_Get_affinity(
648 const Processor_mask *affinity
657 bool _Scheduler_Set_affinity(
660 const cpu_set_t *cpuset
679 ( *extract )( scheduler, the_thread, node );
684 ( *schedule )( scheduler, the_thread, true );
692 #if defined(RTEMS_SMP) 695 return _Processor_mask_Count( &context->Processors );
706 OBJECTS_FAKE_OBJECTS_API,
707 OBJECTS_FAKE_OBJECTS_SCHEDULERS,
709 (uint16_t) ( scheduler_index + 1 )
715 uint32_t minimum_id = _Scheduler_Build_id( 0 );
717 return id - minimum_id;
726 index = _Scheduler_Get_index_by_id(
id );
742 #if defined(RTEMS_SMP) 761 typedef void ( *Scheduler_Release_idle_thread )(
768 Thread_Scheduler_state new_state
772 _ISR_lock_Is_owner( &the_thread->
Scheduler.Lock )
773 || the_thread->
Scheduler.state == THREAD_SCHEDULER_BLOCKED
774 || !_System_state_Is_up( _System_state_Get() )
785 _Assert( _Scheduler_Node_get_idle( node ) ==
NULL );
787 _Scheduler_Node_get_owner( node ) == _Scheduler_Node_get_user( node )
790 _Scheduler_Node_set_user( node, idle );
811 Scheduler_Get_idle_thread get_idle_thread
816 _Scheduler_Set_idle_thread( node, idle );
817 _Thread_Set_CPU( idle, cpu );
822 SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE,
823 SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE,
824 SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK
825 } Scheduler_Try_to_schedule_action;
839 _Scheduler_Try_to_schedule_node(
843 Scheduler_Get_idle_thread get_idle_thread
847 Scheduler_Try_to_schedule_action action;
850 action = SCHEDULER_TRY_TO_SCHEDULE_DO_SCHEDULE;
851 owner = _Scheduler_Node_get_owner( node );
852 _Assert( _Scheduler_Node_get_user( node ) == owner );
853 _Assert( _Scheduler_Node_get_idle( node ) ==
NULL );
855 _Thread_Scheduler_acquire_critical( owner, &lock_context );
857 if ( owner->
Scheduler.state == THREAD_SCHEDULER_READY ) {
858 _Thread_Scheduler_cancel_need_for_help( owner, _Thread_Get_CPU( owner ) );
859 _Scheduler_Thread_change_state( owner, THREAD_SCHEDULER_SCHEDULED );
861 owner->
Scheduler.state == THREAD_SCHEDULER_SCHEDULED
862 && node->sticky_level <= 1
864 action = SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK;
865 }
else if ( node->sticky_level == 0 ) {
866 action = SCHEDULER_TRY_TO_SCHEDULE_DO_BLOCK;
867 }
else if ( idle !=
NULL ) {
868 action = SCHEDULER_TRY_TO_SCHEDULE_DO_IDLE_EXCHANGE;
870 _Scheduler_Use_idle_thread(
873 _Thread_Get_CPU( owner ),
878 _Thread_Scheduler_release_critical( owner, &lock_context );
895 Scheduler_Release_idle_thread release_idle_thread
900 if ( idle !=
NULL ) {
904 _Scheduler_Node_set_user( node, owner );
905 ( *release_idle_thread )(
context, idle );
917 uses_idle->idle =
NULL;
918 _Scheduler_Node_set_user(
920 _Scheduler_Node_get_owner( uses_idle )
922 _Scheduler_Set_idle_thread( needs_idle, idle );
945 Scheduler_Get_idle_thread get_idle_thread
952 sticky_level = node->sticky_level;
954 node->sticky_level = sticky_level;
955 _Assert( sticky_level >= 0 );
957 _Thread_Scheduler_acquire_critical( thread, &lock_context );
958 thread_cpu = _Thread_Get_CPU( thread );
959 _Thread_Scheduler_cancel_need_for_help( thread, thread_cpu );
960 _Scheduler_Thread_change_state( thread, THREAD_SCHEDULER_BLOCKED );
961 _Thread_Scheduler_release_critical( thread, &lock_context );
963 if ( sticky_level > 0 ) {
964 if ( is_scheduled && _Scheduler_Node_get_idle( node ) ==
NULL ) {
967 idle = _Scheduler_Use_idle_thread(
973 _Thread_Dispatch_update_heir( _Per_CPU_Get(), thread_cpu, idle );
979 _Assert( thread == _Scheduler_Node_get_user( node ) );
987 Scheduler_Release_idle_thread release_idle_thread
994 idle = _Scheduler_Node_get_idle( node );
995 owner = _Scheduler_Node_get_owner( node );
998 _Assert( _Scheduler_Node_get_user( node ) == idle );
999 _Scheduler_Node_set_user( node, owner );
1000 ( *release_idle_thread )(
context, idle );
1002 cpu = _Thread_Get_CPU( idle );
1003 _Thread_Set_CPU( the_thread, cpu );
1004 _Thread_Dispatch_update_heir( _Per_CPU_Get(), cpu, the_thread );
1024 Scheduler_Release_idle_thread release_idle_thread
1029 ++node->sticky_level;
1030 _Assert( node->sticky_level > 0 );
1032 if ( is_scheduled ) {
1033 _Scheduler_Discard_idle_thread(
1039 _Scheduler_Thread_change_state( the_thread, THREAD_SCHEDULER_SCHEDULED );
1042 _Scheduler_Thread_change_state( the_thread, THREAD_SCHEDULER_READY );
1057 if ( heir != new_heir && ( heir->
is_preemptible || force_dispatch ) ) {
1058 #if defined(RTEMS_SMP) 1065 heir->
Scheduler.state = THREAD_SCHEDULER_BLOCKED;
1066 new_heir->
Scheduler.state = THREAD_SCHEDULER_SCHEDULED;
1068 _Thread_Update_CPU_time_used( heir, _Thread_Get_CPU( heir ) );
1069 _Thread_Heir = new_heir;
1070 _Thread_Dispatch_necessary =
true;
1082 #if defined(RTEMS_SMP) 1089 return STATUS_RESOURCE_IN_USE;
1092 old_scheduler_node = _Thread_Scheduler_get_home_node( the_thread );
1093 _Priority_Plain_extract(
1094 &old_scheduler_node->
Wait.Priority,
1099 !_Priority_Is_empty( &old_scheduler_node->
Wait.Priority )
1100 #
if defined(RTEMS_SMP)
1105 _Priority_Plain_insert(
1106 &old_scheduler_node->
Wait.Priority,
1110 return STATUS_RESOURCE_IN_USE;
1113 #if defined(RTEMS_SMP) 1114 old_scheduler = _Thread_Scheduler_get_home( the_thread );
1115 new_scheduler_node = _Thread_Scheduler_get_node_by_index(
1117 _Scheduler_Get_index( new_scheduler )
1123 _Scheduler_Get_processor_count( new_scheduler ) == 0
1124 || !( *new_scheduler->
Operations.set_affinity )(
1132 _Priority_Plain_insert(
1133 &old_scheduler_node->
Wait.Priority,
1137 return STATUS_UNSATISFIED;
1141 the_thread->
Scheduler.home_scheduler = new_scheduler;
1145 _Thread_Scheduler_process_requests( the_thread );
1147 new_scheduler_node = old_scheduler_node;
1151 _Priority_Node_set_priority( &the_thread->
Real_priority, priority );
1152 _Priority_Initialize_one(
1153 &new_scheduler_node->
Wait.Priority,
1157 #if defined(RTEMS_SMP) 1158 if ( old_scheduler != new_scheduler ) {
1167 _Assert( old_scheduler_node->sticky_level == 0 );
1168 _Assert( new_scheduler_node->sticky_level == 0 );
1174 &new_scheduler_node->Thread.Wait_node
1177 &old_scheduler_node->Thread.Scheduler_node.Chain
1182 &new_scheduler_node->Thread.Scheduler_node.Chain
1185 _Scheduler_Node_set_priority( new_scheduler_node, priority,
false );
1191 return STATUS_SUCCESSFUL;
1195 _Scheduler_Node_set_priority( new_scheduler_node, priority,
false );
1197 return STATUS_SUCCESSFUL;
RTEMS_INLINE_ROUTINE void _Scheduler_Block(Thread_Control *the_thread)
Blocks a thread with respect to the scheduler.
Definition: schedulerimpl.h:238
RTEMS_INLINE_ROUTINE void _Scheduler_Update_priority(Thread_Control *the_thread)
Propagates a priority change of a thread to the scheduler.
Definition: schedulerimpl.h:335
bool is_preemptible
Definition: thread.h:798
Scheduler context.
Definition: scheduler.h:249
Thread_Wait_information Wait
Definition: thread.h:770
Thread queue context for the thread queue methods.
Definition: threadq.h:193
The priority node to build up a priority aggregation.
Definition: priority.h:94
struct _Thread_Control * executing
This is the thread executing on this processor.
Definition: percpu.h:362
void(* block)(const Scheduler_Control *, Thread_Control *, Scheduler_Node *)
Definition: scheduler.h:60
#define _ISR_lock_Acquire(_lock, _context)
Acquires an ISR lock inside an ISR disabled section.
Definition: isrlock.h:278
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:65
Thread_Start_information Start
Definition: thread.h:828
RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Map_priority(const Scheduler_Control *scheduler, Priority_Control priority)
Maps a thread priority from the user domain to the scheduler domain.
Definition: schedulerimpl.h:448
RTEMS_INLINE_ROUTINE bool _Thread_Is_executing(const Thread_Control *the_thread)
Definition: threadimpl.h:645
RTEMS_INLINE_ROUTINE void _Scheduler_Unblock(Thread_Control *the_thread)
Unblocks a thread with respect to the scheduler.
Definition: schedulerimpl.h:300
RTEMS_INLINE_ROUTINE void _Scheduler_Schedule(Thread_Control *the_thread)
General scheduling decision.
Definition: schedulerimpl.h:192
Priority_Control priority
The priority value of this node.
Definition: priority.h:106
Thread_Scheduler_control Scheduler
Scheduler related control.
Definition: thread.h:767
Priority_Control(* unmap_priority)(const Scheduler_Control *, Priority_Control)
Definition: scheduler.h:87
RTEMS_INLINE_ROUTINE void _Scheduler_Cancel_job(Thread_Control *the_thread, Priority_Node *priority_node, Thread_queue_Context *queue_context)
Cancels a job of a thread with respect to the scheduler.
Definition: schedulerimpl.h:553
RTEMS_INLINE_ROUTINE Chain_Node * _Chain_Next(const Chain_Node *the_node)
Return pointer the next node from this node.
Definition: chainimpl.h:324
RTEMS_INLINE_ROUTINE void _Chain_Extract_unprotected(Chain_Node *the_node)
Extract this node (unprotected).
Definition: chainimpl.h:557
void(* yield)(const Scheduler_Control *, Thread_Control *, Scheduler_Node *)
Definition: scheduler.h:53
void(* node_initialize)(const Scheduler_Control *, Scheduler_Node *, Thread_Control *, Priority_Control)
Definition: scheduler.h:195
RTEMS_INLINE_ROUTINE bool _Processor_mask_Is_subset(const Processor_mask *big, const Processor_mask *small)
Returns true if the processor set small is a subset of processor set big, and false otherwise...
Definition: processormask.h:128
void(* node_destroy)(const Scheduler_Control *, Scheduler_Node *)
Definition: scheduler.h:203
uint64_t Priority_Control
The thread priority control.
Definition: priority.h:66
RTEMS_INLINE_ROUTINE bool _Chain_Is_empty(const Chain_Control *the_chain)
Is the chain empty.
Definition: chainimpl.h:390
RTEMS_INLINE_ROUTINE void _Scheduler_Acquire_critical(const Scheduler_Control *scheduler, ISR_lock_Context *lock_context)
Acquires the scheduler instance inside a critical section (interrupts disabled).
Definition: schedulerimpl.h:105
RTEMS_INLINE_ROUTINE void _Scheduler_Node_destroy(const Scheduler_Control *scheduler, Scheduler_Node *node)
Destroys a scheduler node.
Definition: schedulerimpl.h:509
RTEMS_INLINE_ROUTINE Chain_Node * _Chain_First(const Chain_Control *the_chain)
Return pointer to chain's first node.
Definition: chainimpl.h:257
void(* tick)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:223
RTEMS_INLINE_ROUTINE bool _Thread_Is_heir(const Thread_Control *the_thread)
Definition: threadimpl.h:673
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:597
RTEMS_INLINE_ROUTINE bool _Chain_Has_only_one_node(const Chain_Control *the_chain)
Does this chain have only one node.
Definition: chainimpl.h:449
Per CPU Core Structure.
Definition: percpu.h:290
RTEMS_INLINE_ROUTINE void _Scheduler_Release_critical(const Scheduler_Control *scheduler, ISR_lock_Context *lock_context)
Releases the scheduler instance inside a critical section (interrupts disabled).
Definition: schedulerimpl.h:129
#define _ISR_lock_Release(_lock, _context)
Releases an ISR lock inside an ISR disabled section.
Definition: isrlock.h:301
RTEMS_INLINE_ROUTINE Priority_Control _Scheduler_Unmap_priority(const Scheduler_Control *scheduler, Priority_Control priority)
Unmaps a thread priority from the scheduler domain to the user domain.
Definition: schedulerimpl.h:464
void(* schedule)(const Scheduler_Control *, Thread_Control *)
Definition: scheduler.h:50
States_Control current_state
Definition: thread.h:752
void(* unblock)(const Scheduler_Control *, Thread_Control *, Scheduler_Node *)
Definition: scheduler.h:67
RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(Thread_Control *the_thread, Priority_Node *priority_node, uint64_t deadline, Thread_queue_Context *queue_context)
Releases a job of a thread with respect to the scheduler.
Definition: schedulerimpl.h:526
void(* cancel_job)(const Scheduler_Control *, Thread_Control *, Priority_Node *, Thread_queue_Context *)
Definition: scheduler.h:215
struct Scheduler_Node::@3976 Wait
Thread wait support block.
uint32_t States_Control
Definition: states.h:41
Priority_Control(* map_priority)(const Scheduler_Control *, Priority_Control)
Definition: scheduler.h:81
void(* update_priority)(const Scheduler_Control *, Thread_Control *, Scheduler_Node *)
Definition: scheduler.h:74
RTEMS_INLINE_ROUTINE void _Scheduler_Node_initialize(const Scheduler_Control *scheduler, Scheduler_Node *node, Thread_Control *the_thread, Priority_Control priority)
Initializes a scheduler node.
Definition: schedulerimpl.h:485
unsigned context
Definition: tlb.h:108
Scheduler_Operations Operations
The scheduler operations.
Definition: scheduler.h:275
Scheduler control.
Definition: scheduler.h:266
Scheduler node for per-thread data.
Definition: schedulernode.h:65
const Scheduler_Control _Scheduler_Table[]
Registered schedulers.
Inlined Routines from the Thread Handler.
RTEMS_INLINE_ROUTINE void _Scheduler_Tick(const Per_CPU_Control *cpu)
Scheduler method invoked at each clock tick.
Definition: schedulerimpl.h:578
RTEMS_INLINE_ROUTINE bool _States_Is_ready(States_Control the_states)
Definition: statesimpl.h:185
void(* start_idle)(const Scheduler_Control *, Thread_Control *, struct Per_CPU_Control *)
Definition: scheduler.h:226
RTEMS_INLINE_ROUTINE void _Scheduler_Yield(Thread_Control *the_thread)
Scheduler yield with a particular thread.
Definition: schedulerimpl.h:213
#define _Objects_Build_id(the_api, the_class, node, index)
Definition: object.h:312
Scheduler_Context * context
Reference to a statically allocated scheduler context.
Definition: scheduler.h:270
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
RTEMS_INLINE_ROUTINE const Chain_Node * _Chain_Immutable_tail(const Chain_Control *the_chain)
Return pointer to immutable chain tail.
Definition: chainimpl.h:240
uint32_t Objects_Id
Definition: object.h:75
void _Scheduler_Handler_initialization(void)
Initializes the scheduler to the policy chosen by the user.
Definition: scheduler.c:23
Priority_Node Real_priority
The base priority of this thread in its home scheduler instance.
Definition: thread.h:757
Constants and Structures Associated with the Scheduler.
#define _Objects_Local_node
Definition: objectimpl.h:70
void(* release_job)(const Scheduler_Control *, Thread_Control *, Priority_Node *, uint64_t, Thread_queue_Context *)
Definition: scheduler.h:206
RTEMS_INLINE_ROUTINE void _Chain_Initialize_one(Chain_Control *the_chain, Chain_Node *the_node)
Initializes this chain to contain exactly the specified node.
Definition: chainimpl.h:527
SuperCore SMP Implementation.
#define NULL
Requests a GPIO pin group configuration.
Definition: bestcomm_api.h:77
#define _Scheduler_Count
Count of registered schedulers.
Definition: scheduler.h:314