Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSScoreThread
0007  *
0008  * @brief This source file contains the implementation of
0009  *   _Thread_Create_idle().
0010  */
0011 
0012 /*
0013  *  COPYRIGHT (c) 1989-2011.
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/score/threadimpl.h>
0043 
0044 #include <rtems/score/assert.h>
0045 #include <rtems/score/cpuimpl.h>
0046 #include <rtems/score/interr.h>
0047 #include <rtems/score/schedulerimpl.h>
0048 #include <rtems/score/stackimpl.h>
0049 #include <rtems/score/sysstate.h>
0050 #include <rtems/score/threadidledata.h>
0051 #include <rtems/score/tls.h>
0052 #include <rtems/score/userextimpl.h>
0053 
0054 #include <string.h>
0055 
0056 static void _Thread_Create_idle_for_CPU(
0057   Per_CPU_Control *cpu,
0058   uintptr_t        storage_size
0059 )
0060 {
0061   Thread_Configuration  config;
0062   Thread_Control       *idle;
0063   Status_Control        status;
0064 
0065   memset( &config, 0, sizeof( config ) );
0066   config.scheduler = _Scheduler_Get_by_CPU( cpu );
0067   _Assert( config.scheduler != NULL );
0068   config.priority = _Scheduler_Map_priority(
0069     config.scheduler,
0070     config.scheduler->maximum_priority
0071   );
0072   config.name = _Objects_Build_name( 'I', 'D', 'L', 'E' );
0073   config.is_fp = CPU_IDLE_TASK_IS_FP;
0074   config.is_preemptible = true;
0075   config.stack_free = _Objects_Free_nothing;
0076   config.stack_size = storage_size;
0077 
0078   /*
0079    * The IDLE thread stacks may be statically allocated or there may be a
0080    * custom allocator provided just as with user threads.
0081    */
0082   config.stack_area = ( *_Stack_Allocator_allocate_for_idle )(
0083     _Per_CPU_Get_index( cpu ),
0084     &config.stack_size
0085   );
0086 
0087   if ( config.stack_size < storage_size ) {
0088     _Internal_error( INTERNAL_ERROR_IDLE_THREAD_STACK_TOO_SMALL );
0089   }
0090 
0091   /*
0092    *  The entire workspace is zeroed during its initialization.  Thus, all
0093    *  fields not explicitly assigned were explicitly zeroed by
0094    *  _Workspace_Initialization.
0095    */
0096   idle = _Thread_Internal_allocate();
0097   _Assert( idle != NULL );
0098 
0099   status = _Thread_Initialize( &_Thread_Information, idle, &config );
0100   if ( status != STATUS_SUCCESSFUL ) {
0101     _Internal_error( INTERNAL_ERROR_IDLE_THREAD_CREATE_FAILED );
0102   }
0103 
0104   /*
0105    *  WARNING!!! This is necessary to "kick" start the system and
0106    *             MUST be done before _Thread_Start is invoked.
0107    */
0108   cpu->heir      = idle;
0109   cpu->executing = idle;
0110 #if defined(RTEMS_SMP)
0111   cpu->ancestor = idle;
0112 #endif
0113 
0114   idle->is_idle = true;
0115   idle->Start.Entry.adaptor = _Thread_Entry_adaptor_idle;
0116   idle->Start.Entry.Kinds.Idle.entry = _Thread_Idle_body;
0117 
0118   _Thread_Load_environment( idle );
0119 
0120   idle->current_state = STATES_READY;
0121   _Scheduler_Start_idle( config.scheduler, idle, cpu );
0122   _User_extensions_Thread_start( idle );
0123 }
0124 
0125 void _Thread_Create_idle( void )
0126 {
0127   uintptr_t storage_size;
0128 #if defined(RTEMS_SMP)
0129   uint32_t  cpu_max;
0130   uint32_t  cpu_index;
0131 #endif
0132 
0133   storage_size = _TLS_Get_allocation_size() +
0134     CPU_IDLE_TASK_IS_FP * CONTEXT_FP_SIZE +
0135     _Thread_Idle_stack_size;
0136 
0137 #if defined(RTEMS_SMP)
0138   cpu_max = _SMP_Get_processor_maximum();
0139 
0140   for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
0141     Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
0142 
0143     if ( _Per_CPU_Is_processor_online( cpu ) ) {
0144       _Thread_Create_idle_for_CPU( cpu, storage_size );
0145     }
0146   }
0147 #else
0148   _Thread_Create_idle_for_CPU( _Per_CPU_Get(), storage_size );
0149 #endif
0150 
0151   _CPU_Use_thread_local_storage(
0152     &_Per_CPU_Get_executing( _Per_CPU_Get() )->Registers
0153   );
0154   _System_state_Set( SYSTEM_STATE_BEFORE_MULTITASKING );
0155 }