File indexing completed on 2025-05-11 08:24:22
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 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040
0041 #include <rtems/rtems/scheduler.h>
0042 #include <rtems/score/schedulerimpl.h>
0043 #include <rtems/config.h>
0044
0045 #if defined(RTEMS_SMP)
0046 typedef struct {
0047 const Scheduler_Control *scheduler;
0048 rtems_status_code status;
0049 } Scheduler_Processor_removal_context;
0050
0051 static bool _Scheduler_Check_processor_not_required(
0052 Thread_Control *the_thread,
0053 void *arg
0054 )
0055 {
0056 Scheduler_Processor_removal_context *iter_context;
0057 Thread_queue_Context queue_context;
0058 ISR_lock_Context state_context;
0059
0060 if ( the_thread->is_idle ) {
0061 return false;
0062 }
0063
0064 iter_context = arg;
0065
0066 _Thread_queue_Context_initialize( &queue_context );
0067 _Thread_Wait_acquire( the_thread, &queue_context );
0068 _Thread_State_acquire_critical( the_thread, &state_context );
0069
0070 if (
0071 _Thread_Scheduler_get_home( the_thread ) == iter_context->scheduler
0072 && !_Processor_mask_Has_overlap(
0073 &the_thread->Scheduler.Affinity,
0074 _Scheduler_Get_processors( iter_context->scheduler )
0075 )
0076 ) {
0077 iter_context->status = RTEMS_RESOURCE_IN_USE;
0078 }
0079
0080 _Thread_State_release_critical( the_thread, &state_context );
0081 _Thread_Wait_release( the_thread, &queue_context );
0082 return iter_context->status != RTEMS_SUCCESSFUL;
0083 }
0084
0085 static bool _Scheduler_Check_no_helping(
0086 Thread_Control *the_thread,
0087 void *arg
0088 )
0089 {
0090 Scheduler_Processor_removal_context *iter_context;
0091 ISR_lock_Context lock_context;
0092 const Chain_Node *node;
0093 const Chain_Node *tail;
0094
0095 if ( the_thread->is_idle ) {
0096 return false;
0097 }
0098
0099 iter_context = arg;
0100
0101 _Thread_State_acquire( the_thread, &lock_context );
0102 node = _Chain_Immutable_first( &the_thread->Scheduler.Scheduler_nodes );
0103 tail = _Chain_Immutable_tail( &the_thread->Scheduler.Scheduler_nodes );
0104
0105 do {
0106 const Scheduler_Node *scheduler_node;
0107 const Scheduler_Control *scheduler;
0108
0109 scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
0110 scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
0111
0112 if ( scheduler == iter_context->scheduler ) {
0113 iter_context->status = RTEMS_RESOURCE_IN_USE;
0114 break;
0115 }
0116
0117 node = _Chain_Immutable_next( node );
0118 } while ( node != tail );
0119
0120 _Thread_State_release( the_thread, &lock_context );
0121 return iter_context->status != RTEMS_SUCCESSFUL;
0122 }
0123 #endif
0124
0125 rtems_status_code rtems_scheduler_remove_processor(
0126 rtems_id scheduler_id,
0127 uint32_t cpu_index
0128 )
0129 {
0130 const Scheduler_Control *scheduler;
0131 #if defined(RTEMS_SMP)
0132 Scheduler_Processor_removal_context iter_context;
0133 ISR_lock_Context lock_context;
0134 Scheduler_Context *scheduler_context;
0135 Per_CPU_Control *cpu;
0136 Per_CPU_Control *cpu_self;
0137 #endif
0138
0139 scheduler = _Scheduler_Get_by_id( scheduler_id );
0140 if ( scheduler == NULL ) {
0141 return RTEMS_INVALID_ID;
0142 }
0143
0144 if ( cpu_index >= rtems_configuration_get_maximum_processors() ) {
0145 return RTEMS_INVALID_NUMBER;
0146 }
0147
0148 #if defined(RTEMS_SMP)
0149 iter_context.scheduler = scheduler;
0150 iter_context.status = RTEMS_SUCCESSFUL;
0151 scheduler_context = _Scheduler_Get_context( scheduler );
0152 cpu = _Per_CPU_Get_by_index( cpu_index );
0153
0154 _Objects_Allocator_lock();
0155
0156 if ( cpu->Scheduler.control != scheduler ) {
0157 _Objects_Allocator_unlock();
0158 return RTEMS_INVALID_NUMBER;
0159 }
0160
0161
0162
0163
0164
0165 _ISR_lock_ISR_disable( &lock_context );
0166 _Scheduler_Acquire_critical( scheduler, &lock_context );
0167 _Processor_mask_Clear( &scheduler_context->Processors, cpu_index );
0168 _Scheduler_Release_critical( scheduler, &lock_context );
0169 _ISR_lock_ISR_enable( &lock_context );
0170
0171 _Thread_Iterate( _Scheduler_Check_processor_not_required, &iter_context );
0172
0173 if (
0174 _Processor_mask_Is_zero( &scheduler_context->Processors ) &&
0175 iter_context.status == RTEMS_SUCCESSFUL
0176 ) {
0177 _Thread_Iterate( _Scheduler_Check_no_helping, &iter_context );
0178 }
0179
0180 _ISR_lock_ISR_disable( &lock_context );
0181 _Scheduler_Acquire_critical( scheduler, &lock_context );
0182
0183 if ( iter_context.status == RTEMS_SUCCESSFUL ) {
0184 Thread_Control *idle;
0185 Scheduler_Node *scheduler_node;
0186
0187 cpu->Scheduler.control = NULL;
0188 cpu->Scheduler.context = NULL;
0189 idle = ( *scheduler->Operations.remove_processor )( scheduler, cpu );
0190 cpu->Scheduler.idle_if_online_and_unused = idle;
0191
0192 scheduler_node = _Thread_Scheduler_get_home_node( idle );
0193 _Priority_Plain_extract(
0194 &scheduler_node->Wait.Priority,
0195 &idle->Real_priority
0196 );
0197 _Assert( _Priority_Is_empty( &scheduler_node->Wait.Priority ) );
0198 _Chain_Extract_unprotected( &scheduler_node->Thread.Wait_node );
0199 _Assert( _Chain_Is_empty( &idle->Scheduler.Wait_nodes ) );
0200 _Chain_Extract_unprotected( &scheduler_node->Thread.Scheduler_node.Chain );
0201 _Assert( _Chain_Is_empty( &idle->Scheduler.Scheduler_nodes ) );
0202 } else {
0203 _Processor_mask_Set( &scheduler_context->Processors, cpu_index );
0204 }
0205
0206 cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
0207 _Scheduler_Release_critical( scheduler, &lock_context );
0208 _ISR_lock_ISR_enable( &lock_context );
0209 _Thread_Dispatch_direct( cpu_self );
0210 _Objects_Allocator_unlock();
0211 return iter_context.status;
0212 #else
0213 return RTEMS_RESOURCE_IN_USE;
0214 #endif
0215 }