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

5
Last change on this file since ad87de4 was ad87de4, checked in by Sebastian Huber <sebastian.huber@…>, on 04/11/19 at 06:54:29

score: Rename _SMP_Get_processor_count()

Rename _SMP_Get_processor_count() in _SMP_Get_processor_maximum() to be
in line with the API level rtems_scheduler_get_processor_maximum().

Update #3732.

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