source: rtems/cpukit/score/src/smp.c @ 68ef65b

5
Last change on this file since 68ef65b was 1c46b80, checked in by Sebastian Huber <sebastian.huber@…>, on 11/07/16 at 05:25:03

score: Add scheduler to per-CPU information

This makes it possible to adjust the scheduler of a processor at
run-time.

Update #2797.

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