source: rtems/cpukit/score/src/smp.c @ 99fc1d1d

5
Last change on this file since 99fc1d1d was ceb0f659, checked in by Sebastian Huber <sebastian.huber@…>, on 05/17/16 at 14:03:46

score: Remove the Giant lock

Update #2555.

  • Property mode set to 100644
File size: 6.0 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.org/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/schedulerimpl.h>
24#include <rtems/score/threadimpl.h>
25#include <rtems/config.h>
26
27#if CPU_USE_DEFERRED_FP_SWITCH == TRUE
28  #error "deferred FP switch not implemented for SMP"
29#endif
30
31Processor_mask _SMP_Online_processors;
32
33uint32_t _SMP_Processor_count;
34
35static void _SMP_Start_processors( uint32_t cpu_count )
36{
37  uint32_t cpu_index_self = _SMP_Get_current_processor();
38  uint32_t cpu_index;
39
40  for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) {
41    const Scheduler_Assignment *assignment =
42      _Scheduler_Get_assignment( cpu_index );
43    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
44    bool started;
45
46    if ( cpu_index != cpu_index_self ) {
47      if ( _Scheduler_Should_start_processor( assignment ) ) {
48        started = _CPU_SMP_Start_processor( cpu_index );
49
50        if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) {
51          _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED );
52        }
53      } else {
54        started = false;
55      }
56    } else {
57      started = true;
58
59      cpu->boot = true;
60
61      if ( !_Scheduler_Should_start_processor( assignment ) ) {
62        _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
63      }
64    }
65
66    cpu->online = started;
67
68    if ( started ) {
69      Scheduler_Context *context =
70        _Scheduler_Get_context( assignment->scheduler );
71
72      ++context->processor_count;
73      cpu->scheduler_context = context;
74
75      _Processor_mask_Set( _SMP_Online_processors, cpu_index );
76    }
77  }
78}
79
80void _SMP_Handler_initialize( void )
81{
82  uint32_t cpu_max = rtems_configuration_get_maximum_processors();
83  uint32_t cpu_count;
84  uint32_t cpu_index;
85
86  for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
87    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
88
89    _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
90    _SMP_ticket_lock_Initialize( &cpu->Lock );
91    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
92  }
93
94  /*
95   * Discover and initialize the secondary cores in an SMP system.
96   */
97
98  cpu_count = _CPU_SMP_Initialize();
99  cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
100  _SMP_Processor_count = cpu_count;
101
102  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
103    const Scheduler_Assignment *assignment =
104      _Scheduler_Get_assignment( cpu_index );
105
106    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
107      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
108    }
109  }
110
111  _SMP_Start_processors( cpu_count );
112
113  _CPU_SMP_Finalize_initialization( cpu_count );
114}
115
116void _SMP_Request_start_multitasking( void )
117{
118  Per_CPU_Control *self_cpu = _Per_CPU_Get();
119  uint32_t cpu_count = _SMP_Get_processor_count();
120  uint32_t cpu_index;
121
122  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
123
124  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
125    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
126
127    if ( _Per_CPU_Is_processor_online( cpu ) ) {
128      _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
129    }
130  }
131}
132
133bool _SMP_Should_start_processor( uint32_t cpu_index )
134{
135  const Scheduler_Assignment *assignment =
136    _Scheduler_Get_assignment( cpu_index );
137
138  return _Scheduler_Should_start_processor( assignment );
139}
140
141void _SMP_Start_multitasking_on_secondary_processor( void )
142{
143  Per_CPU_Control *self_cpu = _Per_CPU_Get();
144  uint32_t cpu_index_self = _Per_CPU_Get_index( self_cpu );
145
146  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
147    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
148  }
149
150  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
151    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
152  }
153
154  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
155
156  _Thread_Start_multitasking();
157}
158
159void _SMP_Request_shutdown( void )
160{
161  Per_CPU_Control *self_cpu = _Per_CPU_Get();
162
163  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN );
164}
165
166void _SMP_Send_message( uint32_t cpu_index, unsigned long message )
167{
168  Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
169
170  _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELAXED );
171
172  _CPU_SMP_Send_interrupt( cpu_index );
173}
174
175void _SMP_Send_message_broadcast( unsigned long message )
176{
177  uint32_t cpu_count = _SMP_Get_processor_count();
178  uint32_t cpu_index_self = _SMP_Get_current_processor();
179  uint32_t cpu_index;
180
181  _Assert( _Debug_Is_thread_dispatching_allowed() );
182
183  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
184    if (
185      cpu_index != cpu_index_self
186        && _Processor_mask_Is_set( _SMP_Online_processors, cpu_index )
187    ) {
188      _SMP_Send_message( cpu_index, message );
189    }
190  }
191}
192
193void _SMP_Send_message_multicast(
194    const size_t setsize,
195    const cpu_set_t *cpus,
196    unsigned long message
197)
198{
199  uint32_t cpu_count = _SMP_Get_processor_count();
200  uint32_t cpu_index;
201
202  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
203    if ( CPU_ISSET_S( cpu_index, setsize, cpus ) ) {
204      _SMP_Send_message( cpu_index, message );
205    }
206  }
207}
208
209bool _SMP_Before_multitasking_action_broadcast(
210  SMP_Action_handler  handler,
211  void               *arg
212)
213{
214  bool done = true;
215  uint32_t cpu_count = _SMP_Get_processor_count();
216  uint32_t cpu_index;
217
218  for ( cpu_index = 0 ; done && cpu_index < cpu_count ; ++cpu_index ) {
219    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
220
221    if (
222      !_Per_CPU_Is_boot_processor( cpu )
223        && _Per_CPU_Is_processor_online( cpu )
224    ) {
225      done = _SMP_Before_multitasking_action( cpu, handler, arg );
226    }
227  }
228
229  return done;
230}
231
232SMP_Test_message_handler _SMP_Test_message_handler;
Note: See TracBrowser for help on using the repository browser.