source: rtems/cpukit/score/src/smp.c @ 46f05b92

5
Last change on this file since 46f05b92 was 46f05b92, checked in by Sebastian Huber <sebastian.huber@…>, on 04/05/17 at 09:28:46

SMP: Simplify SMP multicast actions

  • Property mode set to 100644
File size: 6.8 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 const Scheduler_Assignment *_Scheduler_Get_initial_assignment(
36  uint32_t cpu_index
37)
38{
39  return &_Scheduler_Initial_assignments[ cpu_index ];
40}
41
42static bool _Scheduler_Is_mandatory_processor(
43  const Scheduler_Assignment *assignment
44)
45{
46  return (assignment->attributes & SCHEDULER_ASSIGN_PROCESSOR_MANDATORY) != 0;
47}
48
49static bool _Scheduler_Should_start_processor(
50  const Scheduler_Assignment *assignment
51)
52{
53  return assignment->scheduler != NULL;
54}
55
56static void _SMP_Start_processors( uint32_t cpu_count )
57{
58  uint32_t cpu_index_self;
59  uint32_t cpu_index;
60
61  cpu_index_self = _SMP_Get_current_processor();
62
63  for ( cpu_index = 0 ; cpu_index < cpu_count; ++cpu_index ) {
64    const Scheduler_Assignment *assignment;
65    Per_CPU_Control            *cpu;
66    bool                        started;
67
68    assignment = _Scheduler_Get_initial_assignment( cpu_index );
69    cpu = _Per_CPU_Get_by_index( cpu_index );
70
71    if ( cpu_index != cpu_index_self ) {
72      if ( _Scheduler_Should_start_processor( assignment ) ) {
73        started = _CPU_SMP_Start_processor( cpu_index );
74
75        if ( !started && _Scheduler_Is_mandatory_processor( assignment ) ) {
76          _SMP_Fatal( SMP_FATAL_START_OF_MANDATORY_PROCESSOR_FAILED );
77        }
78      } else {
79        started = false;
80      }
81    } else {
82      started = true;
83
84      cpu->boot = true;
85
86      if ( !_Scheduler_Should_start_processor( assignment ) ) {
87        _SMP_Fatal( SMP_FATAL_BOOT_PROCESSOR_NOT_ASSIGNED_TO_SCHEDULER );
88      }
89    }
90
91    cpu->online = started;
92
93    if ( started ) {
94      const Scheduler_Control *scheduler;
95      Scheduler_Context       *context;
96
97      scheduler = assignment->scheduler;
98      context = _Scheduler_Get_context( scheduler );
99
100      ++context->processor_count;
101      cpu->Scheduler.control = scheduler;
102      cpu->Scheduler.context = context;
103
104      _Processor_mask_Set( _SMP_Online_processors, cpu_index );
105    }
106  }
107}
108
109void _SMP_Handler_initialize( void )
110{
111  uint32_t cpu_max = rtems_configuration_get_maximum_processors();
112  uint32_t cpu_count;
113  uint32_t cpu_index;
114
115  for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
116    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
117
118    _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
119    _SMP_ticket_lock_Initialize( &cpu->Lock );
120    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
121    _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
122  }
123
124  /*
125   * Discover and initialize the secondary cores in an SMP system.
126   */
127
128  cpu_count = _CPU_SMP_Initialize();
129  cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
130  _SMP_Processor_count = cpu_count;
131
132  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
133    const Scheduler_Assignment *assignment;
134
135    assignment = _Scheduler_Get_initial_assignment( cpu_index );
136
137    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
138      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
139    }
140  }
141
142  _SMP_Start_processors( cpu_count );
143
144  _CPU_SMP_Finalize_initialization( cpu_count );
145}
146
147void _SMP_Request_start_multitasking( void )
148{
149  Per_CPU_Control *self_cpu = _Per_CPU_Get();
150  uint32_t cpu_count = _SMP_Get_processor_count();
151  uint32_t cpu_index;
152
153  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
154
155  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
156    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
157
158    if ( _Per_CPU_Is_processor_online( cpu ) ) {
159      _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
160    }
161  }
162}
163
164bool _SMP_Should_start_processor( uint32_t cpu_index )
165{
166  const Scheduler_Assignment *assignment;
167
168  assignment = _Scheduler_Get_initial_assignment( cpu_index );
169  return _Scheduler_Should_start_processor( assignment );
170}
171
172void _SMP_Start_multitasking_on_secondary_processor( void )
173{
174  Per_CPU_Control *self_cpu = _Per_CPU_Get();
175  uint32_t cpu_index_self = _Per_CPU_Get_index( self_cpu );
176
177  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
178    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
179  }
180
181  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
182    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
183  }
184
185  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
186
187  _Thread_Start_multitasking();
188}
189
190void _SMP_Request_shutdown( void )
191{
192  ISR_Level level;
193
194  _ISR_Local_disable( level );
195  (void) level;
196
197  _Per_CPU_State_change( _Per_CPU_Get(), PER_CPU_STATE_SHUTDOWN );
198}
199
200void _SMP_Send_message( uint32_t cpu_index, unsigned long message )
201{
202  Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
203
204  _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELEASE );
205
206  _CPU_SMP_Send_interrupt( cpu_index );
207}
208
209void _SMP_Send_message_broadcast( unsigned long message )
210{
211  uint32_t cpu_count = _SMP_Get_processor_count();
212  uint32_t cpu_index_self = _SMP_Get_current_processor();
213  uint32_t cpu_index;
214
215  _Assert( _Debug_Is_thread_dispatching_allowed() );
216
217  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
218    if (
219      cpu_index != cpu_index_self
220        && _Processor_mask_Is_set( _SMP_Online_processors, cpu_index )
221    ) {
222      _SMP_Send_message( cpu_index, message );
223    }
224  }
225}
226
227void _SMP_Send_message_multicast(
228  const Processor_mask targets,
229  unsigned long        message
230)
231{
232  uint32_t cpu_count = _SMP_Get_processor_count();
233  uint32_t cpu_index;
234
235  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
236    if ( _Processor_mask_Is_set( targets, cpu_index ) ) {
237      _SMP_Send_message( cpu_index, message );
238    }
239  }
240}
241
242bool _SMP_Before_multitasking_action_broadcast(
243  SMP_Action_handler  handler,
244  void               *arg
245)
246{
247  bool done = true;
248  uint32_t cpu_count = _SMP_Get_processor_count();
249  uint32_t cpu_index;
250
251  for ( cpu_index = 0 ; done && cpu_index < cpu_count ; ++cpu_index ) {
252    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
253
254    if (
255      !_Per_CPU_Is_boot_processor( cpu )
256        && _Per_CPU_Is_processor_online( cpu )
257    ) {
258      done = _SMP_Before_multitasking_action( cpu, handler, arg );
259    }
260  }
261
262  return done;
263}
264
265SMP_Test_message_handler _SMP_Test_message_handler;
Note: See TracBrowser for help on using the repository browser.