RTEMS
percpu.c
Go to the documentation of this file.
1 
9 /*
10  * COPYRIGHT (c) 1989-2011.
11  * On-Line Applications Research Corporation (OAR).
12  *
13  * The license and distribution terms for this file may be
14  * found in the file LICENSE in this distribution or at
15  * http://www.rtems.org/license/LICENSE.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include <rtems/score/percpu.h>
23 #include <rtems/score/assert.h>
24 #include <rtems/score/isrlock.h>
25 #include <rtems/score/smpimpl.h>
26 #include <rtems/config.h>
27 
29  sizeof( CPU_Uint32ptr ) >= sizeof( uintptr_t ),
30  CPU_Uint32ptr_greater_equal_uintptr_t
31 );
32 
34  sizeof( CPU_Uint32ptr ) >= sizeof( uint32_t ),
35  CPU_Uint32ptr_greater_equal_uint32_t
36 );
37 
38 #if defined(RTEMS_SMP)
39 
40 ISR_LOCK_DEFINE( static, _Per_CPU_State_lock, "Per-CPU State" )
41 
42 static void _Per_CPU_State_acquire( ISR_lock_Context *lock_context )
43 {
44  _ISR_lock_ISR_disable_and_acquire( &_Per_CPU_State_lock, lock_context );
45 }
46 
47 static void _Per_CPU_State_release( ISR_lock_Context *lock_context )
48 {
49  _ISR_lock_Release_and_ISR_enable( &_Per_CPU_State_lock, lock_context );
50 }
51 
52 static void _Per_CPU_State_busy_wait(
53  Per_CPU_Control *cpu,
54  Per_CPU_State new_state
55 )
56 {
57  Per_CPU_State state = cpu->state;
58 
59  switch ( new_state ) {
61  while (
63  && state != PER_CPU_STATE_SHUTDOWN
64  ) {
65  _Per_CPU_Perform_jobs( cpu );
66  _CPU_SMP_Processor_event_receive();
67  state = cpu->state;
68  }
69  break;
70  case PER_CPU_STATE_UP:
71  while (
73  && state != PER_CPU_STATE_SHUTDOWN
74  ) {
75  _Per_CPU_Perform_jobs( cpu );
76  _CPU_SMP_Processor_event_receive();
77  state = cpu->state;
78  }
79  break;
80  default:
81  /* No need to wait */
82  break;
83  }
84 }
85 
86 static Per_CPU_State _Per_CPU_State_get_next(
87  Per_CPU_State current_state,
88  Per_CPU_State new_state
89 )
90 {
91  switch ( current_state ) {
93  switch ( new_state ) {
96  /* Change is acceptable */
97  break;
98  default:
99  new_state = PER_CPU_STATE_SHUTDOWN;
100  break;
101  }
102  break;
104  switch ( new_state ) {
107  /* Change is acceptable */
108  break;
109  default:
110  new_state = PER_CPU_STATE_SHUTDOWN;
111  break;
112  }
113  break;
115  switch ( new_state ) {
116  case PER_CPU_STATE_UP:
118  /* Change is acceptable */
119  break;
120  default:
121  new_state = PER_CPU_STATE_SHUTDOWN;
122  break;
123  }
124  break;
125  default:
126  new_state = PER_CPU_STATE_SHUTDOWN;
127  break;
128  }
129 
130  return new_state;
131 }
132 
133 void _Per_CPU_State_change(
134  Per_CPU_Control *cpu,
135  Per_CPU_State new_state
136 )
137 {
138  ISR_lock_Context lock_context;
139  Per_CPU_State next_state;
140 
141  _Per_CPU_State_busy_wait( cpu, new_state );
142 
143  _Per_CPU_State_acquire( &lock_context );
144 
145  next_state = _Per_CPU_State_get_next( cpu->state, new_state );
146  cpu->state = next_state;
147 
148  if ( next_state == PER_CPU_STATE_SHUTDOWN ) {
149  uint32_t cpu_max = rtems_configuration_get_maximum_processors();
150  uint32_t cpu_index;
151 
152  for ( cpu_index = 0 ; cpu_index < cpu_max ; ++cpu_index ) {
153  Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index( cpu_index );
154 
155  if ( cpu_other != cpu ) {
156  switch ( cpu_other->state ) {
157  case PER_CPU_STATE_UP:
159  break;
160  default:
161  /* Nothing to do */
162  break;
163  }
164 
165  cpu_other->state = PER_CPU_STATE_SHUTDOWN;
166  }
167  }
168  }
169 
170  _CPU_SMP_Processor_event_broadcast();
171 
172  _Per_CPU_State_release( &lock_context );
173 
174  if (
175  next_state == PER_CPU_STATE_SHUTDOWN
176  && new_state != PER_CPU_STATE_SHUTDOWN
177  ) {
178  _SMP_Fatal( SMP_FATAL_SHUTDOWN );
179  }
180 }
181 #else
182  /*
183  * On single core systems, we can efficiently directly access a single
184  * statically allocated per cpu structure. And the fields are initialized
185  * as individual elements just like it has always been done.
186  */
187  Per_CPU_Control_envelope _Per_CPU_Information[1];
188 #endif
The per CPU controls are initialized to zero.
Definition: percpu.h:137
void _Per_CPU_Perform_jobs(Per_CPU_Control *cpu)
Performs the jobs of the specified processor in FIFO order.
Processor is ready to start multitasking.
Definition: percpu.h:153
#define _ISR_lock_Release_and_ISR_enable(_lock, _context)
Releases an ISR lock.
Definition: isrlock.h:257
This header file defines parts of the application configuration information API.
Information for the Assert Handler.
Per CPU Core Structure.
Definition: percpu.h:347
static void _SMP_Fatal(SMP_Fatal_code code)
Terminates with the given code.
Definition: smpimpl.h:72
uintptr_t CPU_Uint32ptr
Definition: cpu.h:1141
#define SMP_MESSAGE_SHUTDOWN
SMP message to request a processor shutdown.
Definition: smpimpl.h:43
#define RTEMS_STATIC_ASSERT(_cond, _msg)
Asserts at compile time that the specified condition is satisfied.
Definition: basedefs.h:838
#define _ISR_lock_ISR_disable_and_acquire(_lock, _context)
Acquires an ISR lock.
Definition: isrlock.h:232
Per_CPU_State state
Indicates the current state of the CPU.
Definition: percpu.h:552
This is the terminal state.
Definition: percpu.h:173
Normal multitasking state.
Definition: percpu.h:168
Per_CPU_State
State of a processor.
Definition: percpu.h:128
#define ISR_LOCK_DEFINE(_qualifier, _designator, _name)
Defines an ISR lock variable.
Definition: isrlock.h:118
Local ISR lock context for acquire and release pairs.
Definition: isrlock.h:65
#define rtems_configuration_get_maximum_processors()
Returns the maximum number of processors which are configured for this application.
Definition: config.h:194
ISR Locks.
void _SMP_Send_message(uint32_t cpu_index, unsigned long message)
Sends an SMP message to a processor.
Definition: smp.c:215
Multitasking start of processor is requested.
Definition: percpu.h:163
SuperCore SMP Implementation.