source: rtems/cpukit/score/src/smp.c @ 3c103ba

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

score: Add _Per_CPU_Is_boot_processor()

  • Property mode set to 100644
File size: 5.7 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    _SMP_ticket_lock_Initialize( &cpu->Lock );
91    _SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
92  }
93
94  /*
95   * Discover and initialize the secondary cores in an SMP system.
96   */
97
98  cpu_count = _CPU_SMP_Initialize();
99  cpu_count = cpu_count < cpu_max ? cpu_count : cpu_max;
100  _SMP_Processor_count = cpu_count;
101
102  for ( cpu_index = cpu_count ; cpu_index < cpu_max; ++cpu_index ) {
103    const Scheduler_Assignment *assignment =
104      _Scheduler_Get_assignment( cpu_index );
105
106    if ( _Scheduler_Is_mandatory_processor( assignment ) ) {
107      _SMP_Fatal( SMP_FATAL_MANDATORY_PROCESSOR_NOT_PRESENT );
108    }
109  }
110
111  _SMP_Start_processors( cpu_count );
112
113  _CPU_SMP_Finalize_initialization( cpu_count );
114}
115
116void _SMP_Request_start_multitasking( void )
117{
118  Per_CPU_Control *self_cpu = _Per_CPU_Get();
119  uint32_t cpu_count = _SMP_Get_processor_count();
120  uint32_t cpu_index;
121
122  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
123
124  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
125    Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
126
127    if ( _Per_CPU_Is_processor_online( cpu ) ) {
128      _Per_CPU_State_change( cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
129    }
130  }
131}
132
133bool _SMP_Should_start_processor( uint32_t cpu_index )
134{
135  const Scheduler_Assignment *assignment =
136    _Scheduler_Get_assignment( cpu_index );
137
138  return _Scheduler_Should_start_processor( assignment );
139}
140
141void _SMP_Start_multitasking_on_secondary_processor( void )
142{
143  Per_CPU_Control *self_cpu = _Per_CPU_Get();
144  uint32_t cpu_index_self = _Per_CPU_Get_index( self_cpu );
145
146  if ( cpu_index_self >= rtems_configuration_get_maximum_processors() ) {
147    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_INVALID_PROCESSOR );
148  }
149
150  if ( !_SMP_Should_start_processor( cpu_index_self ) ) {
151    _SMP_Fatal( SMP_FATAL_MULTITASKING_START_ON_UNASSIGNED_PROCESSOR );
152  }
153
154  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
155
156  _Thread_Start_multitasking();
157}
158
159void _SMP_Request_shutdown( void )
160{
161  Per_CPU_Control *self_cpu = _Per_CPU_Get();
162
163  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN );
164
165  /*
166   * We have to drop the Giant lock here in order to give other processors the
167   * opportunity to receive the inter-processor interrupts issued previously.
168   * In case the executing thread still holds SMP locks, then other processors
169   * already waiting for this SMP lock will spin forever.
170   */
171  _Giant_Drop( self_cpu );
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_RELAXED );
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 ( cpu_index != cpu_index_self ) {
193      _SMP_Send_message( cpu_index, message );
194    }
195  }
196}
197
198void _SMP_Send_message_multicast(
199    const size_t setsize,
200    const cpu_set_t *cpus,
201    unsigned long message
202)
203{
204  uint32_t cpu_count = _SMP_Get_processor_count();
205  uint32_t cpu_index;
206
207  for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
208    if ( CPU_ISSET_S( cpu_index, setsize, cpus ) ) {
209      _SMP_Send_message( cpu_index, message );
210    }
211  }
212}
213
214SMP_Test_message_handler _SMP_Test_message_handler;
Note: See TracBrowser for help on using the repository browser.