source: rtems/cpukit/score/src/smp.c @ c4ff027

4.115
Last change on this file since c4ff027 was c4ff027, checked in by Sebastian Huber <sebastian.huber@…>, on 02/18/14 at 12:30:28

score: Wait for per-CPU state changes later

Wait for per-CPU changes into PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
later. There is no need to delay the initialization of the main
processor at this point.

  • Property mode set to 100644
File size: 4.2 KB
Line 
1/**
2 *  @file
3 *
4 *  @brief SMP Support
5 *  @ingroup Score
6 */
7
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
14 *  http://www.rtems.com/license/LICENSE.
15 */
16
17#if HAVE_CONFIG_H
18#include "config.h"
19#endif
20
21#include <rtems/score/smpimpl.h>
22#include <rtems/score/assert.h>
23#include <rtems/score/threaddispatch.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/config.h>
26#include <rtems/fatal.h>
27
28#if defined(RTEMS_DEBUG)
29  #include <rtems/bspIo.h>
30#endif
31
32void _SMP_Handler_initialize( void )
33{
34  uint32_t max_cpus = rtems_configuration_get_maximum_processors();
35  uint32_t cpu;
36
37  for ( cpu = 0 ; cpu < max_cpus; ++cpu ) {
38    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
39
40    _ISR_lock_Initialize( &per_cpu->lock );
41  }
42
43  /*
44   * Discover and initialize the secondary cores in an SMP system.
45   */
46  max_cpus = _CPU_SMP_Initialize( max_cpus );
47
48  _SMP_Processor_count = max_cpus;
49}
50
51void _SMP_Start_multitasking_on_secondary_processor( void )
52{
53  Per_CPU_Control *self_cpu = _Per_CPU_Get();
54
55  #if defined(RTEMS_DEBUG)
56    printk( "Made it to %d -- ", _Per_CPU_Get_index( self_cpu ) );
57  #endif
58
59  _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
60
61  _Per_CPU_Wait_for_state( self_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
62
63  _Thread_Start_multitasking();
64}
65
66void _SMP_Inter_processor_interrupt_handler( void )
67{
68  Per_CPU_Control *self_cpu = _Per_CPU_Get();
69
70
71  if ( self_cpu->message != 0 ) {
72    uint32_t  message;
73    ISR_Level level;
74
75    _Per_CPU_ISR_disable_and_acquire( self_cpu, level );
76    message = self_cpu->message;
77    self_cpu->message = 0;
78    _Per_CPU_Release_and_ISR_enable( self_cpu, level );
79
80    #if defined(RTEMS_DEBUG)
81      {
82        void *sp = __builtin_frame_address(0);
83        if ( !(message & SMP_MESSAGE_SHUTDOWN) ) {
84          printk(
85            "ISR on CPU %d -- (0x%02x) (0x%p)\n",
86            _Per_CPU_Get_index( self_cpu ),
87            message,
88            sp
89          );
90          if ( message & SMP_MESSAGE_SHUTDOWN )
91            printk( "shutdown\n" );
92        }
93        printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
94      }
95    #endif
96
97    if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
98      _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_SHUTDOWN );
99
100      rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
101      /* does not continue past here */
102    }
103  }
104}
105
106void _SMP_Send_message( uint32_t cpu, uint32_t message )
107{
108  Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
109  ISR_Level level;
110
111  _Per_CPU_ISR_disable_and_acquire( per_cpu, level );
112  per_cpu->message |= message;
113  _Per_CPU_Release_and_ISR_enable( per_cpu, level );
114
115  _CPU_SMP_Send_interrupt( cpu );
116}
117
118void _SMP_Broadcast_message( uint32_t message )
119{
120  uint32_t self = _SMP_Get_current_processor();
121  uint32_t ncpus = _SMP_Get_processor_count();
122  uint32_t cpu;
123
124  _Assert_Thread_dispatching_repressed();
125
126  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
127    if ( cpu != self ) {
128      _SMP_Send_message( cpu, message );
129    }
130  }
131}
132
133void _SMP_Request_other_cores_to_perform_first_context_switch( void )
134{
135  uint32_t self = _SMP_Get_current_processor();
136  uint32_t ncpus = _SMP_Get_processor_count();
137  uint32_t cpu;
138
139  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
140    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
141
142    if ( cpu != self ) {
143      _Per_CPU_Wait_for_state(
144        per_cpu,
145        PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
146      );
147
148      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
149    }
150  }
151}
152
153void _SMP_Request_other_cores_to_shutdown( void )
154{
155  uint32_t self = _SMP_Get_current_processor();
156
157  /*
158   * Do not use _SMP_Get_processor_count() since this value might be not
159   * initialized yet.  For example due to a fatal error in the middle of
160   * _CPU_SMP_Initialize().
161   */
162  uint32_t ncpus = rtems_configuration_get_maximum_processors();
163
164  uint32_t cpu;
165
166  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
167    if ( cpu != self ) {
168      const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
169
170      if ( per_cpu->state != PER_CPU_STATE_BEFORE_INITIALIZATION ) {
171        _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
172      }
173    }
174  }
175}
Note: See TracBrowser for help on using the repository browser.