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
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <rtems/rtems/tasksimpl.h>
0043 #include <rtems/rtems/attrimpl.h>
0044 #include <rtems/rtems/eventimpl.h>
0045 #include <rtems/rtems/modesimpl.h>
0046 #include <rtems/rtems/support.h>
0047 #include <rtems/rtems/statusimpl.h>
0048 #include <rtems/score/apimutex.h>
0049 #include <rtems/score/schedulerimpl.h>
0050 #include <rtems/score/stackimpl.h>
0051 #include <rtems/score/threadimpl.h>
0052 #include <rtems/score/userextimpl.h>
0053 #include <rtems/sysinit.h>
0054
0055 #include <string.h>
0056
0057 #define STATUS_ASSERT( status ) \
0058 RTEMS_STATIC_ASSERT( \
0059 (int) STATUS_CLASSIC_##status == (int) RTEMS_##status, \
0060 status \
0061 )
0062
0063 STATUS_ASSERT( INCORRECT_STATE );
0064 STATUS_ASSERT( INTERNAL_ERROR );
0065 STATUS_ASSERT( INVALID_ADDRESS );
0066 STATUS_ASSERT( INVALID_ID );
0067 STATUS_ASSERT( INVALID_NAME );
0068 STATUS_ASSERT( INVALID_NODE );
0069 STATUS_ASSERT( INVALID_NUMBER );
0070 STATUS_ASSERT( INVALID_PRIORITY );
0071 STATUS_ASSERT( INVALID_SIZE );
0072 STATUS_ASSERT( NO_MEMORY );
0073 STATUS_ASSERT( NOT_DEFINED );
0074 STATUS_ASSERT( NOT_OWNER_OF_RESOURCE );
0075 STATUS_ASSERT( OBJECT_WAS_DELETED );
0076 STATUS_ASSERT( PROXY_BLOCKING );
0077 STATUS_ASSERT( RESOURCE_IN_USE );
0078 STATUS_ASSERT( SUCCESSFUL );
0079 STATUS_ASSERT( TIMEOUT );
0080 STATUS_ASSERT( TOO_MANY );
0081 STATUS_ASSERT( UNSATISFIED );
0082
0083 static rtems_status_code _RTEMS_tasks_Prepare_user_stack(
0084 Thread_Configuration *thread_config,
0085 const rtems_task_config *config
0086 )
0087 {
0088 size_t size;
0089
0090 size = _TLS_Get_allocation_size();
0091
0092 if ( config->maximum_thread_local_storage_size < size ) {
0093 return RTEMS_INVALID_SIZE;
0094 }
0095
0096 #if ( CPU_HARDWARE_FP == TRUE ) || ( CPU_SOFTWARE_FP == TRUE )
0097 if ( thread_config->is_fp ) {
0098 size += CONTEXT_FP_SIZE;
0099 }
0100 #endif
0101
0102 size += _Stack_Minimum();
0103
0104 if ( config->storage_size < size ) {
0105 return RTEMS_INVALID_SIZE;
0106 }
0107
0108 thread_config->stack_size = config->storage_size;
0109 thread_config->stack_area = config->storage_area;
0110
0111 if ( config->storage_free != NULL ) {
0112 thread_config->stack_free = config->storage_free;
0113 } else {
0114 thread_config->stack_free = _Objects_Free_nothing;
0115 }
0116
0117 return RTEMS_SUCCESSFUL;
0118 }
0119
0120 rtems_status_code rtems_task_construct(
0121 const rtems_task_config *config,
0122 rtems_id *id
0123 )
0124 {
0125 if ( config == NULL ) {
0126 return RTEMS_INVALID_ADDRESS;
0127 }
0128
0129 return _RTEMS_tasks_Create( config, id, _RTEMS_tasks_Prepare_user_stack );
0130 }
0131
0132 rtems_status_code _RTEMS_tasks_Create(
0133 const rtems_task_config *config,
0134 rtems_id *id,
0135 RTEMS_tasks_Prepare_stack prepare_stack
0136 )
0137 {
0138 Thread_Control *the_thread;
0139 Thread_Configuration thread_config;
0140 #if defined(RTEMS_MULTIPROCESSING)
0141 Objects_MP_Control *the_global_object = NULL;
0142 bool is_global;
0143 #endif
0144 rtems_status_code status;
0145 rtems_attribute attributes;
0146 bool valid;
0147 RTEMS_API_Control *api;
0148 ASR_Information *asr;
0149
0150 if ( !rtems_is_name_valid( config->name ) ) {
0151 return RTEMS_INVALID_NAME;
0152 }
0153
0154 if ( id == NULL ) {
0155 return RTEMS_INVALID_ADDRESS;
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172 attributes = _Attributes_Set( config->attributes, ATTRIBUTES_REQUIRED );
0173 attributes = _Attributes_Clear( attributes, ATTRIBUTES_NOT_SUPPORTED );
0174
0175 memset( &thread_config, 0, sizeof( thread_config ) );
0176 thread_config.isr_level = _Modes_Get_interrupt_level( config->initial_modes );
0177 thread_config.name = config->name;
0178 thread_config.is_fp = _Attributes_Is_floating_point( attributes );
0179 thread_config.is_preemptible = _Modes_Is_preempt( config->initial_modes );
0180
0181 if ( _Modes_Is_timeslice( config->initial_modes ) ) {
0182 thread_config.cpu_budget_operations = &_Thread_CPU_budget_reset_timeslice;
0183 } else {
0184 thread_config.cpu_budget_operations = NULL;
0185 }
0186
0187
0188
0189
0190
0191 if ( !_Attributes_Is_system_task( attributes ) ) {
0192 if ( config->initial_priority == PRIORITY_MINIMUM ) {
0193 return RTEMS_INVALID_PRIORITY;
0194 }
0195 }
0196
0197 thread_config.scheduler =
0198 _Thread_Scheduler_get_home( _Thread_Get_executing() );
0199
0200 thread_config.priority = _RTEMS_Priority_To_core(
0201 thread_config.scheduler,
0202 config->initial_priority,
0203 &valid
0204 );
0205 if ( !valid ) {
0206 return RTEMS_INVALID_PRIORITY;
0207 }
0208
0209 #if defined(RTEMS_MULTIPROCESSING)
0210 if ( !_System_state_Is_multiprocessing ) {
0211 attributes = _Attributes_Clear( attributes, RTEMS_GLOBAL );
0212 }
0213
0214 is_global = _Attributes_Is_global( attributes );
0215 #endif
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 the_thread = _RTEMS_tasks_Allocate();
0227
0228 if ( !the_thread ) {
0229 _Objects_Allocator_unlock();
0230 return RTEMS_TOO_MANY;
0231 }
0232
0233 #if defined(RTEMS_MULTIPROCESSING)
0234 if ( is_global ) {
0235 the_global_object = _Objects_MP_Allocate_global_object();
0236
0237 if ( the_global_object == NULL ) {
0238 _Objects_Free( &_RTEMS_tasks_Information.Objects, &the_thread->Object );
0239 _Objects_Allocator_unlock();
0240 return RTEMS_TOO_MANY;
0241 }
0242 }
0243 #endif
0244
0245 status = ( *prepare_stack )( &thread_config, config );
0246
0247
0248
0249
0250
0251 if ( status == RTEMS_SUCCESSFUL ) {
0252 Status_Control score_status;
0253
0254 score_status = _Thread_Initialize(
0255 &_RTEMS_tasks_Information,
0256 the_thread,
0257 &thread_config
0258 );
0259 status = _Status_Get( score_status );
0260 } else {
0261 _Objects_Free( &_RTEMS_tasks_Information.Objects, &the_thread->Object );
0262 }
0263
0264 if ( status != RTEMS_SUCCESSFUL ) {
0265 #if defined(RTEMS_MULTIPROCESSING)
0266 if ( is_global )
0267 _Objects_MP_Free_global_object( the_global_object );
0268 #endif
0269 _Objects_Allocator_unlock();
0270 return status;
0271 }
0272
0273 api = the_thread->API_Extensions[ THREAD_API_RTEMS ];
0274 asr = &api->Signal;
0275
0276 asr->is_enabled = !_Modes_Is_asr_disabled( config->initial_modes );
0277
0278 *id = the_thread->Object.id;
0279
0280 #if defined(RTEMS_MULTIPROCESSING)
0281 the_thread->is_global = is_global;
0282 if ( is_global ) {
0283
0284 _Objects_MP_Open(
0285 &_RTEMS_tasks_Information.Objects,
0286 the_global_object,
0287 config->name,
0288 the_thread->Object.id
0289 );
0290
0291 _RTEMS_tasks_MP_Send_process_packet(
0292 RTEMS_TASKS_MP_ANNOUNCE_CREATE,
0293 the_thread->Object.id,
0294 config->name
0295 );
0296
0297 }
0298 #endif
0299
0300 _Objects_Allocator_unlock();
0301 return RTEMS_SUCCESSFUL;
0302 }
0303
0304 static void _RTEMS_tasks_Start_extension(
0305 Thread_Control *executing,
0306 Thread_Control *started
0307 )
0308 {
0309 RTEMS_API_Control *api;
0310
0311 api = started->API_Extensions[ THREAD_API_RTEMS ];
0312
0313 _Event_Initialize( &api->Event );
0314 _Event_Initialize( &api->System_event );
0315 }
0316
0317 #if defined(RTEMS_MULTIPROCESSING)
0318 static void _RTEMS_tasks_Terminate_extension( Thread_Control *executing )
0319 {
0320 if ( executing->is_global ) {
0321 _Objects_MP_Close(
0322 &_RTEMS_tasks_Information.Objects,
0323 executing->Object.id
0324 );
0325 _RTEMS_tasks_MP_Send_process_packet(
0326 RTEMS_TASKS_MP_ANNOUNCE_DELETE,
0327 executing->Object.id,
0328 0
0329 );
0330 }
0331 }
0332 #endif
0333
0334 static User_extensions_Control _RTEMS_tasks_User_extensions = {
0335 .Callouts = {
0336 #if defined(RTEMS_MULTIPROCESSING)
0337 .thread_terminate = _RTEMS_tasks_Terminate_extension,
0338 #endif
0339 .thread_start = _RTEMS_tasks_Start_extension,
0340 .thread_restart = _RTEMS_tasks_Start_extension
0341 }
0342 };
0343
0344 static void _RTEMS_tasks_Manager_initialization( void )
0345 {
0346 _Thread_Initialize_information( &_RTEMS_tasks_Information );
0347 _User_extensions_Add_API_set( &_RTEMS_tasks_User_extensions );
0348 }
0349
0350 RTEMS_SYSINIT_ITEM(
0351 _RTEMS_tasks_Manager_initialization,
0352 RTEMS_SYSINIT_CLASSIC_TASKS,
0353 RTEMS_SYSINIT_ORDER_MIDDLE
0354 );