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

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

score: Initialize per-CPU locks

  • Property mode set to 100644
File size: 4.3 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  for ( cpu = 1 ; cpu < max_cpus; ++cpu ) {
51    const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
52
53    _Per_CPU_Wait_for_state(
54      per_cpu,
55      PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
56    );
57  }
58}
59
60void _SMP_Start_multitasking_on_secondary_processor( void )
61{
62  Per_CPU_Control *self_cpu = _Per_CPU_Get();
63
64  #if defined(RTEMS_DEBUG)
65    printk( "Made it to %d -- ", _Per_CPU_Get_index( self_cpu ) );
66  #endif
67
68  _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
69
70  _Per_CPU_Wait_for_state( self_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
71
72  _Thread_Start_multitasking();
73}
74
75void _SMP_Inter_processor_interrupt_handler( void )
76{
77  Per_CPU_Control *self_cpu = _Per_CPU_Get();
78
79
80  if ( self_cpu->message != 0 ) {
81    uint32_t  message;
82    ISR_Level level;
83
84    _Per_CPU_ISR_disable_and_acquire( self_cpu, level );
85    message = self_cpu->message;
86    self_cpu->message = 0;
87    _Per_CPU_Release_and_ISR_enable( self_cpu, level );
88
89    #if defined(RTEMS_DEBUG)
90      {
91        void *sp = __builtin_frame_address(0);
92        if ( !(message & SMP_MESSAGE_SHUTDOWN) ) {
93          printk(
94            "ISR on CPU %d -- (0x%02x) (0x%p)\n",
95            _Per_CPU_Get_index( self_cpu ),
96            message,
97            sp
98          );
99          if ( message & SMP_MESSAGE_SHUTDOWN )
100            printk( "shutdown\n" );
101        }
102        printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
103      }
104    #endif
105
106    if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
107      _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_SHUTDOWN );
108
109      rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
110      /* does not continue past here */
111    }
112  }
113}
114
115void _SMP_Send_message( uint32_t cpu, uint32_t message )
116{
117  Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
118  ISR_Level level;
119
120  _Per_CPU_ISR_disable_and_acquire( per_cpu, level );
121  per_cpu->message |= message;
122  _Per_CPU_Release_and_ISR_enable( per_cpu, level );
123
124  _CPU_SMP_Send_interrupt( cpu );
125}
126
127void _SMP_Broadcast_message( uint32_t message )
128{
129  uint32_t self = _SMP_Get_current_processor();
130  uint32_t ncpus = _SMP_Get_processor_count();
131  uint32_t cpu;
132
133  _Assert_Thread_dispatching_repressed();
134
135  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
136    if ( cpu != self ) {
137      _SMP_Send_message( cpu, message );
138    }
139  }
140}
141
142void _SMP_Request_other_cores_to_perform_first_context_switch( void )
143{
144  uint32_t self = _SMP_Get_current_processor();
145  uint32_t ncpus = _SMP_Get_processor_count();
146  uint32_t cpu;
147
148  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
149    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
150
151    if ( cpu != self ) {
152      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
153    }
154  }
155}
156
157void _SMP_Request_other_cores_to_shutdown( void )
158{
159  uint32_t self = _SMP_Get_current_processor();
160
161  /*
162   * Do not use _SMP_Get_processor_count() since this value might be not
163   * initialized yet.  For example due to a fatal error in the middle of
164   * _CPU_SMP_Initialize().
165   */
166  uint32_t ncpus = rtems_configuration_get_maximum_processors();
167
168  uint32_t cpu;
169
170  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
171    if ( cpu != self ) {
172      const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
173
174      if ( per_cpu->state != PER_CPU_STATE_BEFORE_INITIALIZATION ) {
175        _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
176      }
177    }
178  }
179}
Note: See TracBrowser for help on using the repository browser.