Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:22

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplClassicTask
0007  *
0008  * @brief This source file contains the implementation of
0009  *   rtems_task_construct() and the Task Manager system initialization.
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2014,2016.
0014  *  On-Line Applications Research Corporation (OAR).
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
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    *  Core Thread Initialize insures we get the minimum amount of
0160    *  stack space.
0161    */
0162 
0163   /*
0164    *  Fix the attribute set to match the attributes which
0165    *  this processor (1) requires and (2) is able to support.
0166    *  First add in the required flags for attributes
0167    *  Typically this might include FP if the platform
0168    *  or application required all tasks to be fp aware.
0169    *  Then turn off the requested bits which are not supported.
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    *  Validate the RTEMS API priority and convert it to the core priority range.
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    *  Allocate the thread control block and -- if the task is global --
0219    *  allocate a global object control block.
0220    *
0221    *  NOTE:  This routine does not use the combined allocate and open
0222    *         global object routine (_Objects_MP_Allocate_and_open) because
0223    *         this results in a lack of control over when memory is allocated
0224    *         and can be freed in the event of an error.
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    *  Initialize the core thread for this task.
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                                /* Not used */
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 );