source: rtems/cpukit/score/src/smp.c @ 2548d14

5
Last change on this file since 2548d14 was 406dd62, checked in by Sebastian Huber <sebastian.huber@…>, on 07/24/18 at 09:18:27

_SMP_Start_multitasking_on_secondary_processor()

Pass current processor control as first parameter to make dependency
more explicit.

  • 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      _Processor_mask_Set( &_SMP_Online_processors, cpu_index );
101      _Processor_mask_Set( &context->Processors, cpu_index );
102      cpu->Scheduler.control = scheduler;
103      cpu->Scheduler.context = context;
104    }
105  }
106}
107
108void _SMP_Handler_initialize( void )
109{
110  uint32_t cpu_max = rtems_configuration_get_maximum_processors();
111  uint32_t cpu_count;
112  uint32_t cpu_index;
113
114  for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
115    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
116
117    _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
118    _SMP_ticket_lock_Initialize( &cpu->Lock );
119    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
120    _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
121  }
122
123  /*
124   * Discover and initialize the secondary cores in an SMP system.
125   */
126
127  cpu_count = _CPU_SMP_Initialize();
128  cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
129  _SMP_Processor_count = cpu_count;
130
131  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
132    const Scheduler_Assignment *assignment;
133
134    assignment = _Scheduler_Get_initial_assignment( cpu_index );
135
136    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
137      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
138    }
139  }
140
141  _SMP_Start_processors( cpu_count );
142
143  _CPU_SMP_Finalize_initialization( cpu_count );
144}
145
146void _SMP_Request_start_multitasking( void )
147{
148  Per_CPU_Control *cpu_self;
149  uint32_t         cpu_count;
150  uint32_t         cpu_index;
151
152  cpu_self = _Per_CPU_Get();
153  _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
154
155  cpu_count = _SMP_Get_processor_count();
156
157  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
158    Per_CPU_Control *cpu;
159
160    cpu = _Per_CPU_Get_by_index( cpu_index );
161
162    if ( _Per_CPU_Is_processor_online( cpu ) ) {
163      _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
164    }
165  }
166}
167
168bool _SMP_Should_start_processor( uint32_t cpu_index )
169{
170  const Scheduler_Assignment *assignment;
171
172  assignment = _Scheduler_Get_initial_assignment( cpu_index );
173  return _Scheduler_Should_start_processor( assignment );
174}
175
176void _SMP_Start_multitasking_on_secondary_processor(
177  Per_CPU_Control *cpu_self
178)
179{
180  uint32_t cpu_index_self;
181
182  cpu_index_self = _Per_CPU_Get_index( cpu_self );
183
184  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
185    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
186  }
187
188  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
189    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
190  }
191
192  _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
193
194  _Thread_Start_multitasking();
195}
196
197void _SMP_Request_shutdown( void )
198{
199  ISR_Level level;
200
201  _ISR_Local_disable( level );
202  (void) level;
203
204  _Per_CPU_State_change( _Per_CPU_Get(), PER_CPU_STATE_SHUTDOWN );
205}
206
207void _SMP_Send_message( uint32_t cpu_index, unsigned long message )
208{
209  Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
210
211  _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELEASE );
212
213  _CPU_SMP_Send_interrupt( cpu_index );
214}
215
216void _SMP_Send_message_broadcast( unsigned long message )
217{
218  uint32_t cpu_count = _SMP_Get_processor_count();
219  uint32_t cpu_index_self = _SMP_Get_current_processor();
220  uint32_t cpu_index;
221
222  _Assert( _Debug_Is_thread_dispatching_allowed() );
223
224  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
225    if (
226      cpu_index != cpu_index_self
227        && _Processor_mask_Is_set( &_SMP_Online_processors, cpu_index )
228    ) {
229      _SMP_Send_message( cpu_index, message );
230    }
231  }
232}
233
234void _SMP_Send_message_multicast(
235  const Processor_mask *targets,
236  unsigned long         message
237)
238{
239  uint32_t cpu_count = _SMP_Get_processor_count();
240  uint32_t cpu_index;
241
242  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
243    if ( _Processor_mask_Is_set( targets, cpu_index ) ) {
244      _SMP_Send_message( cpu_index, message );
245    }
246  }
247}
248
249bool _SMP_Before_multitasking_action_broadcast(
250  SMP_Action_handler  handler,
251  void               *arg
252)
253{
254  bool done = true;
255  uint32_t cpu_count = _SMP_Get_processor_count();
256  uint32_t cpu_index;
257
258  for ( cpu_index = 0 ; done && cpu_index < cpu_count ; ++cpu_index ) {
259    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
260
261    if (
262      !_Per_CPU_Is_boot_processor( cpu )
263        && _Per_CPU_Is_processor_online( cpu )
264    ) {
265      done = _SMP_Before_multitasking_action( cpu, handler, arg );
266    }
267  }
268
269  return done;
270}
271
272SMP_Test_message_handler _SMP_Test_message_handler;
Note: See TracBrowser for help on using the repository browser.