source: rtems/cpukit/score/src/smp.c @ 6c36946f

4.115
Last change on this file since 6c36946f was 6c36946f, checked in by Sebastian Huber <sebastian.huber@…>, on 05/07/14 at 12:22:56

score: Fix SMP startup

  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[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]28static 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]69void _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]103void _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]120void _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]133void _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]148void _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]157void _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]172SMP_Test_message_handler _SMP_Test_message_handler;
Note: See TracBrowser for help on using the repository browser.