[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 ) { |
---|
| 61 | ++assignment->scheduler->context->processor_count; |
---|
| 62 | } |
---|
| 63 | } |
---|
| 64 | } |
---|
| 65 | |
---|
[282bfd3] | 66 | void _SMP_Handler_initialize( void ) |
---|
| 67 | { |
---|
[53e008b] | 68 | uint32_t cpu_max = rtems_configuration_get_maximum_processors(); |
---|
| 69 | uint32_t cpu_count; |
---|
| 70 | uint32_t cpu_index; |
---|
[282bfd3] | 71 | |
---|
[53e008b] | 72 | for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) { |
---|
[3380ee8] | 73 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[b1d08a58] | 74 | |
---|
[3380ee8] | 75 | _SMP_ticket_lock_Initialize( &cpu->Lock, "per-CPU" ); |
---|
[b1d08a58] | 76 | } |
---|
| 77 | |
---|
[282bfd3] | 78 | /* |
---|
| 79 | * Discover and initialize the secondary cores in an SMP system. |
---|
| 80 | */ |
---|
| 81 | |
---|
[53e008b] | 82 | cpu_count = _CPU_SMP_Initialize(); |
---|
| 83 | cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max; |
---|
| 84 | _SMP_Processor_count = cpu_count; |
---|
| 85 | |
---|
[c5831a3f] | 86 | for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) { |
---|
| 87 | const Scheduler_Assignment *assignment = |
---|
| 88 | _Scheduler_Get_assignment( cpu_index ); |
---|
[53e008b] | 89 | |
---|
[c5831a3f] | 90 | if ( _Scheduler_Is_mandatory_processor( assignment ) ) { |
---|
| 91 | _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT ); |
---|
[53e008b] | 92 | } |
---|
| 93 | } |
---|
| 94 | |
---|
[c5831a3f] | 95 | _SMP_Start_processors( cpu_count ); |
---|
| 96 | |
---|
[53e008b] | 97 | _CPU_SMP_Finalize_initialization( cpu_count ); |
---|
[282bfd3] | 98 | } |
---|
| 99 | |
---|
[7336be9d] | 100 | void _SMP_Request_start_multitasking( void ) |
---|
[06dcaf0] | 101 | { |
---|
[fe52e7c0] | 102 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[3380ee8] | 103 | uint32_t cpu_count = _SMP_Get_processor_count(); |
---|
| 104 | uint32_t cpu_index; |
---|
[7336be9d] | 105 | |
---|
| 106 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING ); |
---|
[2f6108f9] | 107 | |
---|
[3380ee8] | 108 | for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { |
---|
| 109 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[7336be9d] | 110 | |
---|
[3380ee8] | 111 | _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING ); |
---|
[7336be9d] | 112 | } |
---|
| 113 | } |
---|
[2f6108f9] | 114 | |
---|
[7336be9d] | 115 | void _SMP_Start_multitasking_on_secondary_processor( void ) |
---|
| 116 | { |
---|
| 117 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[2f6108f9] | 118 | |
---|
[c5831a3f] | 119 | if ( !_Per_CPU_Is_processor_started( self_cpu ) ) { |
---|
| 120 | _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR ); |
---|
| 121 | } |
---|
| 122 | |
---|
[7336be9d] | 123 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING ); |
---|
[dad36c52] | 124 | |
---|
[514705d] | 125 | _Thread_Start_multitasking(); |
---|
[06dcaf0] | 126 | } |
---|
| 127 | |
---|
[7336be9d] | 128 | void _SMP_Request_shutdown( void ) |
---|
| 129 | { |
---|
[d50acdbb] | 130 | Per_CPU_Control *self_cpu = _Per_CPU_Get(); |
---|
[7336be9d] | 131 | |
---|
| 132 | _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN ); |
---|
[ba25cc2] | 133 | |
---|
| 134 | /* |
---|
| 135 | * We have to drop the Giant lock here in order to give other processors the |
---|
| 136 | * opportunity to receive the inter-processor interrupts issued previously. |
---|
| 137 | * In case the executing thread still holds SMP locks, then other processors |
---|
| 138 | * already waiting for this SMP lock will spin forever. |
---|
| 139 | */ |
---|
[d50acdbb] | 140 | _Giant_Drop( self_cpu ); |
---|
[7336be9d] | 141 | } |
---|
| 142 | |
---|
[3380ee8] | 143 | void _SMP_Send_message( uint32_t cpu_index, uint32_t message ) |
---|
[06dcaf0] | 144 | { |
---|
[3380ee8] | 145 | Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index ); |
---|
[06dcaf0] | 146 | ISR_Level level; |
---|
| 147 | |
---|
[3380ee8] | 148 | _Per_CPU_ISR_disable_and_acquire( cpu, level ); |
---|
| 149 | cpu->message |= message; |
---|
| 150 | _Per_CPU_Release_and_ISR_enable( cpu, level ); |
---|
[2f6108f9] | 151 | |
---|
[3380ee8] | 152 | _CPU_SMP_Send_interrupt( cpu_index ); |
---|
[06dcaf0] | 153 | } |
---|
| 154 | |
---|
[2f6108f9] | 155 | void _SMP_Broadcast_message( uint32_t message ) |
---|
[06dcaf0] | 156 | { |
---|
[3380ee8] | 157 | uint32_t cpu_count = _SMP_Get_processor_count(); |
---|
| 158 | uint32_t cpu_index_self = _SMP_Get_current_processor(); |
---|
| 159 | uint32_t cpu_index; |
---|
[2f6108f9] | 160 | |
---|
[ff25926] | 161 | _Assert( _Debug_Is_thread_dispatching_allowed() ); |
---|
[f8ff2a0] | 162 | |
---|
[3380ee8] | 163 | for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) { |
---|
| 164 | if ( cpu_index != cpu_index_self ) { |
---|
| 165 | _SMP_Send_message( cpu_index, message ); |
---|
[2f6108f9] | 166 | } |
---|
[06dcaf0] | 167 | } |
---|
| 168 | } |
---|