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

Last change on this file was bf867c55, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 28, 2019 at 12:15:45 PM

score: Remove unused SMP_MESSAGE_TEST

All uses were replaced by per-processor jobs.

  • Property mode set to 100644
File size: 6.3 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;
118
119    cpu = _Per_CPU_Get_by_index( cpu_index );
120    _ISR_lock_Set_name( &cpu->Lock, "Per-CPU" );
121    _ISR_lock_Set_name( &cpu->Jobs.Lock, "Per-CPU Jobs" );
122    _ISR_lock_Set_name( &cpu->Watchdog.Lock, "Per-CPU Watchdog" );
123    _Chain_Initialize_empty( &cpu->Threads_in_need_for_help );
124  }
125
126  /*
127   * Discover and initialize the secondary cores in an SMP system.
128   */
129
130  cpu_max = _CPU_SMP_Initialize();
131  cpu_max = cpu_max < cpu_config_max ? cpu_max : cpu_config_max;
132  _SMP_Processor_maximum = cpu_max;
133
134  for ( cpu_index = cpu_max ; cpu_index < cpu_config_max; ++cpu_index ) {
135    const Scheduler_Assignment *assignment;
136
137    assignment = _Scheduler_Get_initial_assignment( cpu_index );
138
139    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
140      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
141    }
142  }
143
144  _SMP_Start_processors( cpu_max );
145
146  _CPU_SMP_Finalize_initialization( cpu_max );
147}
148
149void _SMP_Request_start_multitasking( void )
150{
151  Per_CPU_Control *cpu_self;
152  uint32_t         cpu_max;
153  uint32_t         cpu_index;
154
155  cpu_self = _Per_CPU_Get();
156  _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
157
158  cpu_max = _SMP_Get_processor_maximum();
159
160  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
161    Per_CPU_Control *cpu;
162
163    cpu = _Per_CPU_Get_by_index( cpu_index );
164
165    if ( _Per_CPU_Is_processor_online( cpu ) ) {
166      _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
167    }
168  }
169}
170
171bool _SMP_Should_start_processor( uint32_t cpu_index )
172{
173  const Scheduler_Assignment *assignment;
174
175  assignment = _Scheduler_Get_initial_assignment( cpu_index );
176  return _Scheduler_Should_start_processor( assignment );
177}
178
179void _SMP_Start_multitasking_on_secondary_processor(
180  Per_CPU_Control *cpu_self
181)
182{
183  uint32_t cpu_index_self;
184
185  cpu_index_self = _Per_CPU_Get_index( cpu_self );
186
187  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
188    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
189  }
190
191  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
192    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
193  }
194
195  _Per_CPU_State_change( cpu_self, PER_CPU_STATE_READY_TO_START_MULTITASKING );
196
197  _Thread_Start_multitasking();
198}
199
200void _SMP_Request_shutdown( void )
201{
202  ISR_Level level;
203
204  _ISR_Local_disable( level );
205  (void) level;
206
207  _Per_CPU_State_change( _Per_CPU_Get(), PER_CPU_STATE_SHUTDOWN );
208}
209
210void _SMP_Send_message( uint32_t cpu_index, unsigned long message )
211{
212  Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
213
214  _Atomic_Fetch_or_ulong( &cpu->message, message, ATOMIC_ORDER_RELEASE );
215
216  _CPU_SMP_Send_interrupt( cpu_index );
217}
218
219void _SMP_Send_message_broadcast( unsigned long message )
220{
221  uint32_t cpu_max;
222  uint32_t cpu_index_self;
223  uint32_t cpu_index;
224
225  _Assert( _Debug_Is_thread_dispatching_allowed() );
226  cpu_max = _SMP_Get_processor_maximum();
227  cpu_index_self = _SMP_Get_current_processor();
228
229  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
230    if (
231      cpu_index != cpu_index_self
232        && _Processor_mask_Is_set( &_SMP_Online_processors, cpu_index )
233    ) {
234      _SMP_Send_message( cpu_index, message );
235    }
236  }
237}
238
239void _SMP_Send_message_multicast(
240  const Processor_mask *targets,
241  unsigned long         message
242)
243{
244  uint32_t cpu_max;
245  uint32_t cpu_index;
246
247  cpu_max = _SMP_Get_processor_maximum();
248
249  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
250    if ( _Processor_mask_Is_set( targets, cpu_index ) ) {
251      _SMP_Send_message( cpu_index, message );
252    }
253  }
254}
Note: See TracBrowser for help on using the repository browser.