[6ca4f6a] | 1 | /** |
---|
| 2 | * @file |
---|
| 3 | * |
---|
| 4 | * @ingroup ScoreSMPImpl |
---|
| 5 | * |
---|
| 6 | * @brief SuperCore SMP Implementation |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
| 10 | * COPYRIGHT (c) 1989-2011. |
---|
| 11 | * On-Line Applications Research Corporation (OAR). |
---|
| 12 | * |
---|
| 13 | * The license and distribution terms for this file may be |
---|
| 14 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 15 | * http://www.rtems.org/license/LICENSE. |
---|
[6ca4f6a] | 16 | */ |
---|
| 17 | |
---|
| 18 | #ifndef _RTEMS_SCORE_SMPIMPL_H |
---|
| 19 | #define _RTEMS_SCORE_SMPIMPL_H |
---|
| 20 | |
---|
| 21 | #include <rtems/score/smp.h> |
---|
[8a65a960] | 22 | #include <rtems/score/percpu.h> |
---|
[b3a4c48e] | 23 | #include <rtems/score/processormask.h> |
---|
[8a65a960] | 24 | #include <rtems/fatal.h> |
---|
[ddbc3f8d] | 25 | #include <rtems/rtems/cache.h> |
---|
[6ca4f6a] | 26 | |
---|
| 27 | #ifdef __cplusplus |
---|
| 28 | extern "C" { |
---|
| 29 | #endif |
---|
| 30 | |
---|
| 31 | /** |
---|
| 32 | * @defgroup ScoreSMP SMP Support |
---|
| 33 | * |
---|
| 34 | * @ingroup Score |
---|
| 35 | * |
---|
| 36 | * This defines the interface of the SuperCore SMP support. |
---|
| 37 | * |
---|
| 38 | * @{ |
---|
| 39 | */ |
---|
| 40 | |
---|
| 41 | /** |
---|
| 42 | * @brief SMP message to request a processor shutdown. |
---|
| 43 | * |
---|
| 44 | * @see _SMP_Send_message(). |
---|
| 45 | */ |
---|
[4d906bda] | 46 | #define SMP_MESSAGE_SHUTDOWN 0x1UL |
---|
[6ca4f6a] | 47 | |
---|
[145becf] | 48 | /** |
---|
| 49 | * @brief SMP message to request a test handler invocation. |
---|
| 50 | * |
---|
| 51 | * @see _SMP_Send_message(). |
---|
| 52 | */ |
---|
[4d906bda] | 53 | #define SMP_MESSAGE_TEST 0x2UL |
---|
[145becf] | 54 | |
---|
[ddbc3f8d] | 55 | /** |
---|
[26c142e5] | 56 | * @brief SMP message to request a multicast action. |
---|
[ddbc3f8d] | 57 | * |
---|
| 58 | * @see _SMP_Send_message(). |
---|
| 59 | */ |
---|
[26c142e5] | 60 | #define SMP_MESSAGE_MULTICAST_ACTION 0x4UL |
---|
[ddbc3f8d] | 61 | |
---|
[90d8567] | 62 | /** |
---|
| 63 | * @brief SMP message to request a clock tick. |
---|
| 64 | * |
---|
| 65 | * This message is provided for systems without a proper interrupt affinity |
---|
| 66 | * support and may be used by the clock driver. |
---|
| 67 | * |
---|
| 68 | * @see _SMP_Send_message(). |
---|
| 69 | */ |
---|
| 70 | #define SMP_MESSAGE_CLOCK_TICK 0x8UL |
---|
| 71 | |
---|
[6ca4f6a] | 72 | /** |
---|
| 73 | * @brief SMP fatal codes. |
---|
| 74 | */ |
---|
| 75 | typedef enum { |
---|
[c5831a3f] | 76 | SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER, |
---|
| 77 | SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT, |
---|
[c952ecab] | 78 | SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR, |
---|
[c5831a3f] | 79 | SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR, |
---|
[c952ecab] | 80 | SMP_FATAL_SHUTDOWN, |
---|
[d134adeb] | 81 | SMP_FATAL_SHUTDOWN_RESPONSE, |
---|
[7097962] | 82 | SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED, |
---|
| 83 | SMP_FATAL_SCHEDULER_PIN_OR_UNPIN_NOT_SUPPORTED |
---|
[6ca4f6a] | 84 | } SMP_Fatal_code; |
---|
| 85 | |
---|
[c5831a3f] | 86 | static inline void _SMP_Fatal( SMP_Fatal_code code ) |
---|
| 87 | { |
---|
[b6606e8] | 88 | _Terminate( RTEMS_FATAL_SOURCE_SMP, code ); |
---|
[c5831a3f] | 89 | } |
---|
| 90 | |
---|
[6ca4f6a] | 91 | /** |
---|
| 92 | * @brief Initialize SMP Handler |
---|
| 93 | * |
---|
| 94 | * This method initialize the SMP Handler. |
---|
| 95 | */ |
---|
| 96 | #if defined( RTEMS_SMP ) |
---|
| 97 | void _SMP_Handler_initialize( void ); |
---|
| 98 | #else |
---|
| 99 | #define _SMP_Handler_initialize() \ |
---|
| 100 | do { } while ( 0 ) |
---|
| 101 | #endif |
---|
| 102 | |
---|
| 103 | #if defined( RTEMS_SMP ) |
---|
| 104 | |
---|
[b3a4c48e] | 105 | /** |
---|
| 106 | * @brief Set of online processors. |
---|
| 107 | * |
---|
| 108 | * A processor is online if was started during system initialization. In this |
---|
| 109 | * case its corresponding bit in the mask is set. |
---|
| 110 | * |
---|
| 111 | * @see _SMP_Handler_initialize(). |
---|
| 112 | */ |
---|
| 113 | extern Processor_mask _SMP_Online_processors; |
---|
| 114 | |
---|
[911b1d2] | 115 | /** |
---|
| 116 | * @brief Performs high-level initialization of a secondary processor and runs |
---|
| 117 | * the application threads. |
---|
| 118 | * |
---|
| 119 | * The low-level initialization code must call this function to hand over the |
---|
| 120 | * control of this processor to RTEMS. Interrupts must be disabled. It must |
---|
| 121 | * be possible to send inter-processor interrupts to this processor. Since |
---|
| 122 | * interrupts are disabled the inter-processor interrupt delivery is postponed |
---|
| 123 | * until interrupts are enabled the first time. Interrupts are enabled during |
---|
| 124 | * the execution begin of threads in case they have interrupt level zero (this |
---|
| 125 | * is the default). |
---|
| 126 | * |
---|
| 127 | * The pre-requisites for the call to this function are |
---|
| 128 | * - disabled interrupts, |
---|
| 129 | * - delivery of inter-processor interrupts is possible, |
---|
| 130 | * - a valid stack pointer and enough stack space, |
---|
| 131 | * - a valid code memory, and |
---|
| 132 | * - a valid BSS section. |
---|
| 133 | * |
---|
| 134 | * This function must not be called by the main processor. The main processor |
---|
| 135 | * uses _Thread_Start_multitasking() instead. |
---|
| 136 | * |
---|
| 137 | * This function does not return to the caller. |
---|
[406dd62] | 138 | * |
---|
| 139 | * @param[in] cpu_self The current processor control. |
---|
[911b1d2] | 140 | */ |
---|
[406dd62] | 141 | void _SMP_Start_multitasking_on_secondary_processor( |
---|
| 142 | Per_CPU_Control *cpu_self |
---|
| 143 | ) RTEMS_NO_RETURN; |
---|
[911b1d2] | 144 | |
---|
[145becf] | 145 | typedef void ( *SMP_Test_message_handler )( Per_CPU_Control *cpu_self ); |
---|
| 146 | |
---|
| 147 | extern SMP_Test_message_handler _SMP_Test_message_handler; |
---|
| 148 | |
---|
| 149 | /** |
---|
| 150 | * @brief Sets the handler for test messages. |
---|
| 151 | * |
---|
| 152 | * This handler can be used to test the inter-processor interrupt |
---|
| 153 | * implementation. |
---|
| 154 | */ |
---|
| 155 | static inline void _SMP_Set_test_message_handler( |
---|
| 156 | SMP_Test_message_handler handler |
---|
| 157 | ) |
---|
| 158 | { |
---|
| 159 | _SMP_Test_message_handler = handler; |
---|
| 160 | } |
---|
| 161 | |
---|
[ddbc3f8d] | 162 | /** |
---|
[26c142e5] | 163 | * @brief Processes all pending multicast actions. |
---|
[ddbc3f8d] | 164 | */ |
---|
[26c142e5] | 165 | void _SMP_Multicast_actions_process( void ); |
---|
[ddbc3f8d] | 166 | |
---|
[4d9bd56] | 167 | /** |
---|
| 168 | * @brief Interrupt handler for inter-processor interrupts. |
---|
[90d8567] | 169 | * |
---|
| 170 | * @return The received message. |
---|
[4d9bd56] | 171 | */ |
---|
[0d362ff3] | 172 | static inline long unsigned _SMP_Inter_processor_interrupt_handler( |
---|
| 173 | Per_CPU_Control *cpu_self |
---|
| 174 | ) |
---|
[8a65a960] | 175 | { |
---|
[0d362ff3] | 176 | unsigned long message; |
---|
[8a65a960] | 177 | |
---|
[258ad71] | 178 | /* |
---|
| 179 | * In the common case the inter-processor interrupt is issued to carry out a |
---|
| 180 | * thread dispatch. |
---|
| 181 | */ |
---|
| 182 | cpu_self->dispatch_necessary = true; |
---|
| 183 | |
---|
[9bb3ce39] | 184 | message = _Atomic_Exchange_ulong( |
---|
| 185 | &cpu_self->message, |
---|
| 186 | 0, |
---|
| 187 | ATOMIC_ORDER_ACQUIRE |
---|
| 188 | ); |
---|
[8a65a960] | 189 | |
---|
[5677883] | 190 | if ( RTEMS_PREDICT_FALSE( message != 0 ) ) { |
---|
[8a65a960] | 191 | if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) { |
---|
[b3049a1d] | 192 | _SMP_Fatal( SMP_FATAL_SHUTDOWN_RESPONSE ); |
---|
[8a65a960] | 193 | /* does not continue past here */ |
---|
| 194 | } |
---|
[145becf] | 195 | |
---|
| 196 | if ( ( message & SMP_MESSAGE_TEST ) != 0 ) { |
---|
| 197 | ( *_SMP_Test_message_handler )( cpu_self ); |
---|
| 198 | } |
---|
[ddbc3f8d] | 199 | |
---|
[26c142e5] | 200 | if ( ( message & SMP_MESSAGE_MULTICAST_ACTION ) != 0 ) { |
---|
| 201 | _SMP_Multicast_actions_process(); |
---|
[ddbc3f8d] | 202 | } |
---|
[8a65a960] | 203 | } |
---|
[90d8567] | 204 | |
---|
| 205 | return message; |
---|
[8a65a960] | 206 | } |
---|
[4d9bd56] | 207 | |
---|
[2a4f9d7] | 208 | /** |
---|
| 209 | * @brief Returns true, if the processor with the specified index should be |
---|
| 210 | * started. |
---|
| 211 | * |
---|
| 212 | * @param[in] cpu_index The processor index. |
---|
| 213 | * |
---|
| 214 | * @retval true The processor should be started. |
---|
| 215 | * @retval false Otherwise. |
---|
| 216 | */ |
---|
| 217 | bool _SMP_Should_start_processor( uint32_t cpu_index ); |
---|
| 218 | |
---|
[6ca4f6a] | 219 | /** |
---|
[90d8567] | 220 | * @brief Sends an SMP message to a processor. |
---|
[6ca4f6a] | 221 | * |
---|
| 222 | * The target processor may be the sending processor. |
---|
| 223 | * |
---|
[3380ee8] | 224 | * @param[in] cpu_index The target processor of the message. |
---|
[6ca4f6a] | 225 | * @param[in] message The message. |
---|
| 226 | */ |
---|
[4d906bda] | 227 | void _SMP_Send_message( uint32_t cpu_index, unsigned long message ); |
---|
[6ca4f6a] | 228 | |
---|
| 229 | /** |
---|
[90d8567] | 230 | * @brief Sends an SMP message to all other online processors. |
---|
[6ca4f6a] | 231 | * |
---|
[90d8567] | 232 | * @param[in] message The message. |
---|
[6ca4f6a] | 233 | */ |
---|
[aed38189] | 234 | void _SMP_Send_message_broadcast( |
---|
| 235 | unsigned long message |
---|
[6ca4f6a] | 236 | ); |
---|
| 237 | |
---|
[a68cc1b] | 238 | /** |
---|
[90d8567] | 239 | * @brief Sends an SMP message to a set of processors. |
---|
[a68cc1b] | 240 | * |
---|
| 241 | * The sending processor may be part of the set. |
---|
| 242 | * |
---|
[46f05b92] | 243 | * @param[in] targets The set of processors to send the message. |
---|
[a68cc1b] | 244 | * @param[in] message The message. |
---|
| 245 | */ |
---|
| 246 | void _SMP_Send_message_multicast( |
---|
[3dfe55ee] | 247 | const Processor_mask *targets, |
---|
| 248 | unsigned long message |
---|
[a68cc1b] | 249 | ); |
---|
| 250 | |
---|
[5b0d2c1] | 251 | typedef void ( *SMP_Action_handler )( void *arg ); |
---|
[26c142e5] | 252 | |
---|
| 253 | /** |
---|
[90d8567] | 254 | * @brief Initiates an SMP multicast action to a set of processors. |
---|
[26c142e5] | 255 | * |
---|
| 256 | * The current processor may be part of the set. |
---|
| 257 | * |
---|
| 258 | * @param[in] setsize The size of the set of target processors of the message. |
---|
| 259 | * @param[in] cpus The set of target processors of the message. |
---|
| 260 | * @param[in] handler The multicast action handler. |
---|
| 261 | * @param[in] arg The multicast action argument. |
---|
| 262 | */ |
---|
| 263 | void _SMP_Multicast_action( |
---|
| 264 | const size_t setsize, |
---|
| 265 | const cpu_set_t *cpus, |
---|
[5b0d2c1] | 266 | SMP_Action_handler handler, |
---|
[26c142e5] | 267 | void *arg |
---|
| 268 | ); |
---|
| 269 | |
---|
[5b0d2c1] | 270 | /** |
---|
| 271 | * @brief Executes a handler with argument on the specified processor on behalf |
---|
| 272 | * of the boot processor. |
---|
| 273 | * |
---|
| 274 | * The calling processor must be the boot processor. In case the specified |
---|
| 275 | * processor is not online or not in the |
---|
| 276 | * PER_CPU_STATE_READY_TO_START_MULTITASKING state, then no action is |
---|
| 277 | * performed. |
---|
| 278 | * |
---|
| 279 | * @param cpu The processor to execute the action. |
---|
| 280 | * @param handler The handler of the action. |
---|
| 281 | * @param arg The argument of the action. |
---|
| 282 | * |
---|
| 283 | * @retval true The handler executed on the specified processor. |
---|
| 284 | * @retval false Otherwise. |
---|
| 285 | * |
---|
| 286 | * @see _SMP_Before_multitasking_action_broadcast(). |
---|
| 287 | */ |
---|
| 288 | bool _SMP_Before_multitasking_action( |
---|
| 289 | Per_CPU_Control *cpu, |
---|
| 290 | SMP_Action_handler handler, |
---|
| 291 | void *arg |
---|
| 292 | ); |
---|
| 293 | |
---|
| 294 | /** |
---|
| 295 | * @brief Executes a handler with argument on all online processors except the |
---|
| 296 | * boot processor on behalf of the boot processor. |
---|
| 297 | * |
---|
| 298 | * The calling processor must be the boot processor. |
---|
| 299 | * |
---|
| 300 | * @param handler The handler of the action. |
---|
| 301 | * @param arg The argument of the action. |
---|
| 302 | * |
---|
| 303 | * @retval true The handler executed on all online processors except the boot |
---|
| 304 | * processor. |
---|
| 305 | * @retval false Otherwise. |
---|
| 306 | * |
---|
| 307 | * @see _SMP_Before_multitasking_action(). |
---|
| 308 | */ |
---|
| 309 | bool _SMP_Before_multitasking_action_broadcast( |
---|
| 310 | SMP_Action_handler handler, |
---|
| 311 | void *arg |
---|
| 312 | ); |
---|
| 313 | |
---|
[6ca4f6a] | 314 | #endif /* defined( RTEMS_SMP ) */ |
---|
| 315 | |
---|
| 316 | /** |
---|
[7336be9d] | 317 | * @brief Requests a multitasking start on all configured and available |
---|
| 318 | * processors. |
---|
[6ca4f6a] | 319 | */ |
---|
| 320 | #if defined( RTEMS_SMP ) |
---|
[7336be9d] | 321 | void _SMP_Request_start_multitasking( void ); |
---|
[6ca4f6a] | 322 | #else |
---|
[7336be9d] | 323 | #define _SMP_Request_start_multitasking() \ |
---|
[6ca4f6a] | 324 | do { } while ( 0 ) |
---|
| 325 | #endif |
---|
| 326 | |
---|
| 327 | /** |
---|
[7336be9d] | 328 | * @brief Requests a shutdown of all processors. |
---|
| 329 | * |
---|
| 330 | * This function is a part of the system termination procedure. |
---|
[6ca4f6a] | 331 | * |
---|
[7336be9d] | 332 | * @see _Terminate(). |
---|
[6ca4f6a] | 333 | */ |
---|
| 334 | #if defined( RTEMS_SMP ) |
---|
[7336be9d] | 335 | void _SMP_Request_shutdown( void ); |
---|
[6ca4f6a] | 336 | #else |
---|
[7336be9d] | 337 | #define _SMP_Request_shutdown() \ |
---|
[6ca4f6a] | 338 | do { } while ( 0 ) |
---|
| 339 | #endif |
---|
| 340 | |
---|
[76d1198] | 341 | RTEMS_INLINE_ROUTINE const Processor_mask *_SMP_Get_online_processors( void ) |
---|
| 342 | { |
---|
| 343 | #if defined(RTEMS_SMP) |
---|
| 344 | return &_SMP_Online_processors; |
---|
| 345 | #else |
---|
[e2623038] | 346 | return &_Processor_mask_The_one_and_only; |
---|
[76d1198] | 347 | #endif |
---|
| 348 | } |
---|
| 349 | |
---|
[6ca4f6a] | 350 | /** @} */ |
---|
| 351 | |
---|
| 352 | #ifdef __cplusplus |
---|
| 353 | } |
---|
| 354 | #endif |
---|
| 355 | |
---|
| 356 | #endif |
---|
| 357 | /* end of include file */ |
---|