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

5
Last change on this file since bbd6d27a was 03b900d, checked in by Sebastian Huber <sebastian.huber@…>, on 02/18/16 at 07:36:26

score: Replace watchdog handler implementation

Use a red-black tree instead of delta chains.

Close #2344.
Update #2554.
Update #2555.
Close #2606.

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