[e655f7e] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @brief SMP Support |
---|
| 5 | * @ingroup Score |
---|
| 6 | */ |
---|
| 7 | |
---|
[06dcaf0] | 8 | /* |
---|
| 9 | * COPYRIGHT (c) 1989-2011. |
---|
| 10 | * On-Line Applications Research Corporation (OAR). |
---|
| 11 | * |
---|
| 12 | * The license and distribution terms for this file may be |
---|
| 13 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 14 | * http://www.rtems.org/license/LICENSE. |
---|
[06dcaf0] | 15 | */ |
---|
| 16 | |
---|
| 17 | #if HAVE_CONFIG_H |
---|
| 18 | #include "config.h" |
---|
| 19 | #endif |
---|
| 20 | |
---|
[6ca4f6a] | 21 | #include <rtems/score/smpimpl.h> |
---|
[f8ff2a0] | 22 | #include <rtems/score/assert.h> |
---|
[c5831a3f] | 23 | #include <rtems/score/schedulerimpl.h> |
---|
[4fc370e] | 24 | #include <rtems/score/threaddispatch.h> |
---|
[b4b309c] | 25 | #include <rtems/score/threadimpl.h> |
---|
[8a6de83] | 26 | #include <rtems/config.h> |
---|
[06dcaf0] | 27 | |
---|
[c5831a3f] | 28 | static void _SMP_Start_processors( uint32_t cpu_count ) |
---|
| 29 | { |
---|
[3380ee8] | 30 | uint32_t cpu_index_self = _SMP_Get_current_processor(); |
---|
[c5831a3f] | 31 | uint32_t cpu_index; |
---|
| 32 | |
---|
| 33 | |
---|
| 34 | for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) { |
---|
| 35 | const Scheduler_Assignment *assignment = |
---|
| 36 | _Scheduler_Get_assignment( cpu_index ); |
---|
[3380ee8] | 37 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[c5831a3f] | 38 | bool started; |
---|
| 39 | |
---|
[3380ee8] | 40 | if ( cpu_index != cpu_index_self ) { |
---|
[c5831a3f] | 41 | if ( _Scheduler_Should_start_processor( assignment ) ) { |
---|
| 42 | started = _CPU_SMP_Start_processor( cpu_index ); |
---|
| 43 | |
---|
| 44 | if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) { |
---|
| 45 | _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED ); |
---|
| 46 | } |
---|
| 47 | } else { |
---|
| 48 | started = false; |
---|
| 49 | } |
---|
| 50 | } else { |
---|
| 51 | started = true; |
---|
| 52 | |
---|
| 53 | if ( !_Scheduler_Should_start_processor( assignment ) ) { |
---|
| 54 | _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER ); |
---|
| 55 | } |
---|
| 56 | } |
---|
| 57 | |
---|
[3380ee8] | 58 | cpu->started = started; |
---|
[c5831a3f] | 59 | |
---|
| 60 | if ( started ) { |
---|
[38b59a6] | 61 | Scheduler_Context *scheduler_context = assignment->scheduler->context; |
---|
| 62 | |
---|
| 63 | ++scheduler_context->processor_count; |
---|
| 64 | cpu->scheduler_context = scheduler_context; |
---|
[c5831a3f] | 65 | } |
---|
| 66 | } |
---|
| 67 | } |
---|
| 68 | |
---|
[282bfd3] | 69 | void _SMP_Handler_initialize( void ) |
---|
| 70 | { |
---|
[53e008b] | 71 | uint32_t cpu_max = rtems_configuration_get_maximum_processors(); |
---|
| 72 | uint32_t cpu_count; |
---|
| 73 | uint32_t cpu_index; |
---|
[282bfd3] | 74 | |
---|
[53e008b] | 75 | for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) { |
---|
[3380ee8] | 76 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[b1d08a58] | 77 | |
---|
[3380ee8] | 78 | _SMP_ticket_lock_Initialize( &cpu->Lock, "per-CPU" ); |
---|
[b1d08a58] | 79 | } |
---|
| 80 | |
---|
[282bfd3] | 81 | /* |
---|
| 82 | * Discover and initialize the secondary cores in an SMP system. |
---|
| 83 | */ |
---|
| 84 | |
---|
[53e008b] | 85 | cpu_count = _CPU_SMP_Initialize(); |
---|
| 86 | cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max; |
---|
| 87 | _SMP_Processor_count = cpu_count; |
---|
| 88 | |
---|
[c5831a3f] | 89 | for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) { |
---|
| 90 | const Scheduler_Assignment *assignment = |
---|
| 91 | _Scheduler_Get_assignment( cpu_index ); |
---|
[53e008b] | 92 | |
---|
[c5831a3f] | 93 | if ( _Scheduler_Is_mandatory_processor( assignment ) ) { |
---|
| 94 | _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT ); |
---|
[53e008b] | 95 | } |
---|
| 96 | } |
---|
| 97 | |
---|
[c5831a3f] | 98 | _SMP_Start_processors( cpu_count ); |
---|
| 99 | |
---|
[53e008b] | 100 | _CPU_SMP_Finalize_initialization( cpu_count ); |
---|
[282bfd3] | 101 | } |
---|
| 102 | |
---|
[7336be9d] | 103 | void _SMP_Request_start_multitasking( void ) |
---|
[06dcaf0] | 104 | { |
---|
[fe52e7c0] | 105 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[3380ee8] | 106 | uint32_t cpu_count = _SMP_Get_processor_count(); |
---|
| 107 | uint32_t cpu_index; |
---|
[7336be9d] | 108 | |
---|
| 109 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING ); |
---|
[2f6108f9] | 110 | |
---|
[3380ee8] | 111 | for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { |
---|
| 112 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[7336be9d] | 113 | |
---|
[6c36946f] | 114 | if ( _Per_CPU_Is_processor_started( cpu ) ) { |
---|
| 115 | _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING ); |
---|
| 116 | } |
---|
[7336be9d] | 117 | } |
---|
| 118 | } |
---|
[2f6108f9] | 119 | |
---|
[7336be9d] | 120 | void _SMP_Start_multitasking_on_secondary_processor( void ) |
---|
| 121 | { |
---|
| 122 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[2f6108f9] | 123 | |
---|
[c5831a3f] | 124 | if ( !_Per_CPU_Is_processor_started( self_cpu ) ) { |
---|
| 125 | _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR ); |
---|
| 126 | } |
---|
| 127 | |
---|
[7336be9d] | 128 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING ); |
---|
[dad36c52] | 129 | |
---|
[514705d] | 130 | _Thread_Start_multitasking(); |
---|
[06dcaf0] | 131 | } |
---|
| 132 | |
---|
[7336be9d] | 133 | void _SMP_Request_shutdown( void ) |
---|
| 134 | { |
---|
[d50acdbb] | 135 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[7336be9d] | 136 | |
---|
| 137 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN ); |
---|
[ba25cc2] | 138 | |
---|
| 139 | /* |
---|
| 140 | * We have to drop the Giant lock here in order to give other processors the |
---|
| 141 | * opportunity to receive the inter-processor interrupts issued previously. |
---|
| 142 | * In case the executing thread still holds SMP locks, then other processors |
---|
| 143 | * already waiting for this SMP lock will spin forever. |
---|
| 144 | */ |
---|
[d50acdbb] | 145 | _Giant_Drop( self_cpu ); |
---|
[7336be9d] | 146 | } |
---|
| 147 | |
---|
[4d906bda] | 148 | void _SMP_Send_message( uint32_t cpu_index, unsigned long message ) |
---|
[06dcaf0] | 149 | { |
---|
[3380ee8] | 150 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[06dcaf0] | 151 | |
---|
[4d906bda] | 152 | _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELAXED ); |
---|
[2f6108f9] | 153 | |
---|
[3380ee8] | 154 | _CPU_SMP_Send_interrupt( cpu_index ); |
---|
[06dcaf0] | 155 | } |
---|
| 156 | |
---|
[2f6108f9] | 157 | void _SMP_Broadcast_message( uint32_t message ) |
---|
[06dcaf0] | 158 | { |
---|
[3380ee8] | 159 | uint32_t cpu_count = _SMP_Get_processor_count(); |
---|
| 160 | uint32_t cpu_index_self = _SMP_Get_current_processor(); |
---|
| 161 | uint32_t cpu_index; |
---|
[2f6108f9] | 162 | |
---|
[ff25926] | 163 | _Assert( _Debug_Is_thread_dispatching_allowed() ); |
---|
[f8ff2a0] | 164 | |
---|
[3380ee8] | 165 | for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { |
---|
| 166 | if ( cpu_index != cpu_index_self ) { |
---|
| 167 | _SMP_Send_message( cpu_index, message ); |
---|
[2f6108f9] | 168 | } |
---|
[06dcaf0] | 169 | } |
---|
| 170 | } |
---|
[145becf] | 171 | |
---|
[58444f7] | 172 | SMP_Test_message_handler _SMP_Test_message_handler; |
---|