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 RTEMSImplClassicScheduler
0007  *
0008  * @brief This source file contains the implementation of
0009  *   rtems_scheduler_add_processor().
0010  */
0011 
0012 /*
0013  * Copyright (c) 2016 embedded brains GmbH & Co. KG
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #ifdef HAVE_CONFIG_H
0038 #include "config.h"
0039 #endif
0040 
0041 #include <rtems/rtems/scheduler.h>
0042 #include <rtems/score/assert.h>
0043 #include <rtems/score/schedulerimpl.h>
0044 #include <rtems/config.h>
0045 
0046 rtems_status_code rtems_scheduler_add_processor(
0047   rtems_id scheduler_id,
0048   uint32_t cpu_index
0049 )
0050 {
0051   uint32_t                 scheduler_index;
0052 #if defined(RTEMS_SMP)
0053   Per_CPU_Control         *cpu;
0054   rtems_status_code        status;
0055 #endif
0056 
0057   scheduler_index = _Scheduler_Get_index_by_id( scheduler_id );
0058 
0059   if ( scheduler_index >= _Scheduler_Count ) {
0060     return RTEMS_INVALID_ID;
0061   }
0062 
0063   if ( cpu_index >= rtems_configuration_get_maximum_processors() ) {
0064     return RTEMS_NOT_CONFIGURED;
0065   }
0066 
0067 #if defined(RTEMS_SMP)
0068   cpu = _Per_CPU_Get_by_index( cpu_index );
0069 
0070   if ( _Scheduler_Initial_assignments[ cpu_index ].scheduler == NULL ) {
0071     return RTEMS_NOT_CONFIGURED;
0072   }
0073 
0074   if ( !_Per_CPU_Is_processor_online( cpu ) ) {
0075     return RTEMS_INCORRECT_STATE;
0076   }
0077 
0078   _Objects_Allocator_lock();
0079 
0080   if ( cpu->Scheduler.control == NULL ) {
0081     const Scheduler_Control *scheduler;
0082     Scheduler_Context       *scheduler_context;
0083     Priority_Control         idle_priority;
0084     Thread_Control          *idle;
0085     Scheduler_Node          *scheduler_node;
0086     ISR_lock_Context         lock_context;
0087     Per_CPU_Control         *cpu_self;
0088 
0089     scheduler = &_Scheduler_Table[ scheduler_index ];
0090     scheduler_context = _Scheduler_Get_context( scheduler );
0091     idle_priority =
0092       _Scheduler_Map_priority( scheduler, scheduler->maximum_priority );
0093 
0094     idle = cpu->Scheduler.idle_if_online_and_unused;
0095     _Assert( idle != NULL );
0096     cpu->Scheduler.idle_if_online_and_unused = NULL;
0097 
0098     idle->Scheduler.home_scheduler = scheduler;
0099     idle->Start.initial_priority = idle_priority;
0100     scheduler_node =
0101       _Thread_Scheduler_get_node_by_index( idle, scheduler_index );
0102     _Priority_Node_set_priority( &idle->Real_priority, idle_priority );
0103     _Priority_Initialize_one(
0104       &scheduler_node->Wait.Priority,
0105       &idle->Real_priority
0106     );
0107     _Assert( _Chain_Is_empty( &idle->Scheduler.Wait_nodes ) );
0108     _Chain_Initialize_one(
0109       &idle->Scheduler.Wait_nodes,
0110       &scheduler_node->Thread.Wait_node
0111     );
0112     _Assert( _Chain_Is_empty( &idle->Scheduler.Scheduler_nodes ) );
0113     _Chain_Initialize_one(
0114       &idle->Scheduler.Scheduler_nodes,
0115       &scheduler_node->Thread.Scheduler_node.Chain
0116     );
0117 
0118     _ISR_lock_ISR_disable( &lock_context );
0119     _Scheduler_Acquire_critical( scheduler, &lock_context );
0120     _Processor_mask_Set( &scheduler_context->Processors, cpu_index );
0121     cpu->Scheduler.control = scheduler;
0122     cpu->Scheduler.context = scheduler_context;
0123     ( *scheduler->Operations.add_processor )( scheduler, idle );
0124     cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
0125     _Scheduler_Release_critical( scheduler, &lock_context );
0126     _ISR_lock_ISR_enable( &lock_context );
0127     _Thread_Dispatch_direct( cpu_self );
0128     status = RTEMS_SUCCESSFUL;
0129   } else {
0130     status = RTEMS_RESOURCE_IN_USE;
0131   }
0132 
0133   _Objects_Allocator_unlock();
0134   return status;
0135 #else
0136   return RTEMS_RESOURCE_IN_USE;
0137 #endif
0138 }