source: rtems/cpukit/score/src/smp.c @ 2d7ae960

4.115
Last change on this file since 2d7ae960 was 9b4422a2, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 15:09:24

Remove All CVS Id Strings Possible Using a Script

Script does what is expected and tries to do it as
smartly as possible.

+ remove occurrences of two blank comment lines

next to each other after Id string line removed.

+ remove entire comment blocks which only exited to

contain CVS Ids

+ If the processing left a blank line at the top of

a file, it was removed.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 *  COPYRIGHT (c) 1989-2011.
3 *  On-Line Applications Research Corporation (OAR).
4 *
5 *  The license and distribution terms for this file may be
6 *  found in the file LICENSE in this distribution or at
7 *  http://www.rtems.com/license/LICENSE.
8 */
9
10#if HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#include <rtems/system.h>
15#include <rtems/bspsmp.h>
16#include <rtems/score/smp.h>
17#include <rtems/score/thread.h>
18
19#if defined(RTEMS_DEBUG)
20  #include <rtems/bspIo.h>
21#endif
22
23/*
24 *  Process request to switch to the first task on a secondary core.
25 */
26void rtems_smp_run_first_task(int cpu)
27{
28  Thread_Control *heir;
29  ISR_Level       level;
30
31  _ISR_Disable_on_this_core( level );
32
33  /*
34   *  The Scheduler will have selected the heir thread for each CPU core.
35   *  Now we have been requested to perform the first context switch.  So
36   *  force a switch to the designated heir and make it executing on
37   *  THIS core.
38   */
39  heir              = _Thread_Heir;
40  _Thread_Executing = heir;
41
42  _CPU_Context_switch_to_first_task_smp( &heir->Registers );
43}
44
45/*
46 *  Process request to initialize this secondary core.
47 */
48void rtems_smp_secondary_cpu_initialize(void)
49{
50  int       cpu;
51  ISR_Level level;
52
53  cpu = bsp_smp_processor_id();
54
55  _ISR_Disable_on_this_core( level );
56  bsp_smp_secondary_cpu_initialize(cpu);
57
58  /*
59   *  Inform the primary CPU that this secondary CPU is initialized
60   *  and ready to dispatch to the first thread it is supposed to
61   *  execute when the primary CPU is ready.
62   */
63  _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_INITIALIZED;
64
65  #if defined(RTEMS_DEBUG)
66    printk( "Made it to %d -- ", cpu );
67  #endif
68
69  /*
70   *  With this secondary core out of reset, we can wait for the
71   *  request to switch to the first task.
72   */
73  while(1) {
74    uint32_t   message;
75
76    bsp_smp_wait_for(
77      (volatile unsigned int *)&_Per_CPU_Information[cpu].message,
78      RTEMS_BSP_SMP_FIRST_TASK,
79      10000
80    );
81
82    level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
83      message = _Per_CPU_Information[cpu].message;
84      if ( message & RTEMS_BSP_SMP_FIRST_TASK ) {
85        _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
86        _ISR_Set_level( 0 );
87      }
88     
89    _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
90  }
91}
92
93/*
94 *  Process an interrupt processor interrupt which indicates a request
95 *  from another core.
96 */
97void rtems_smp_process_interrupt(void)
98{
99  int        cpu;
100  uint32_t   message;
101  ISR_Level  level;
102
103  cpu = bsp_smp_processor_id();
104
105  level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
106  message = _Per_CPU_Information[cpu].message;
107
108  #if defined(RTEMS_DEBUG)
109    {
110      void *sp = __builtin_frame_address(0);
111      if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) {
112        printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp );
113        if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY )
114          printk( "context switch necessary\n" );
115        if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
116          printk( "signal to self\n" );
117        if ( message & RTEMS_BSP_SMP_SHUTDOWN )
118          printk( "shutdown\n" );
119        if ( message & RTEMS_BSP_SMP_FIRST_TASK )
120          printk( "switch to first task\n" );
121      }
122 
123      printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
124    }
125  #endif
126
127  if ( message & RTEMS_BSP_SMP_FIRST_TASK ) {
128    _Per_CPU_Information[cpu].isr_nest_level = 0;
129    _Per_CPU_Information[cpu].message &= ~message;
130    _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_UP;
131
132    _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
133
134    rtems_smp_run_first_task(cpu);
135    /* does not return */
136  }
137
138  if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
139    _Per_CPU_Information[cpu].message &= ~message;
140
141    _Per_CPU_Information[cpu].isr_nest_level = 0;
142    _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_SHUTDOWN;
143    _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
144
145    _Thread_Enable_dispatch();       /* undo ISR code */
146    _ISR_Disable_on_this_core( level );
147    while(1)
148      ;
149    /* does not continue past here */
150  }
151
152  if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY ) {
153    #if defined(RTEMS_DEBUG)
154      printk( "switch needed\n" );
155    #endif
156    _Per_CPU_Information[cpu].message &= ~message;
157    _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
158  }
159}
160
161/*
162 *  Send an interrupt processor request to another cpu.
163 */
164void _SMP_Send_message(
165  int       cpu,
166  uint32_t  message
167)
168{
169  ISR_Level level;
170
171  #if defined(RTEMS_DEBUG)
172    if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
173      printk( "Send 0x%x to %d\n", message, cpu );
174  #endif
175
176  level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
177    _Per_CPU_Information[cpu].message |= message;
178  _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
179  bsp_smp_interrupt_cpu( cpu );
180}
181
182/*
183 *  Send interrupt processor request to all other nodes
184 */
185void _SMP_Broadcast_message(
186  uint32_t  message
187)
188{
189  int        dest_cpu;
190  int        cpu;
191  ISR_Level  level;
192
193  cpu = bsp_smp_processor_id();
194
195  for ( dest_cpu=0 ; dest_cpu <  _SMP_Processor_count; dest_cpu++ ) {
196    if ( cpu == dest_cpu )
197      continue;
198    level = _SMP_lock_spinlock_simple_Obtain( &_Per_CPU_Information[cpu].lock );
199      _Per_CPU_Information[dest_cpu].message |= message;
200    _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
201  }
202  bsp_smp_broadcast_interrupt();
203}
204
205/*
206 *  Send interrupt processor requests to perform first context switch
207 */
208void _SMP_Request_other_cores_to_perform_first_context_switch(void)
209{
210  int    cpu;
211
212  _Per_CPU_Information[cpu].state = RTEMS_BSP_SMP_CPU_UP;
213  for (cpu=1 ; cpu < _SMP_Processor_count ; cpu++ ) {
214    _SMP_Send_message( cpu, RTEMS_BSP_SMP_FIRST_TASK );
215  }
216}
217
218/*
219 *  Send message to other cores requesting them to perform
220 *  a thread dispatch operation.
221 */
222void _SMP_Request_other_cores_to_dispatch(void)
223{
224  int i;
225  int cpu;
226
227  cpu = bsp_smp_processor_id();
228
229  if ( !_System_state_Is_up (_System_state_Current) )
230    return;
231  for (i=1 ; i < _SMP_Processor_count ; i++ ) {
232    if ( cpu == i )
233      continue;
234    if ( _Per_CPU_Information[i].state != RTEMS_BSP_SMP_CPU_UP )
235      continue;
236    if ( !_Per_CPU_Information[i].dispatch_necessary )
237      continue;
238    _SMP_Send_message( i, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY );
239  }
240}
241
242/*
243 *  Send message to other cores requesting them to shutdown.
244 */
245void _SMP_Request_other_cores_to_shutdown(void)
246{
247  bool   allDown;
248  int    ncpus;
249  int    n;
250  int    cpu;
251
252  cpu   = bsp_smp_processor_id();
253  ncpus = _SMP_Processor_count;
254
255  _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN );
256
257  allDown = true;
258  for (n=0 ; n<ncpus ; n++ ) {
259     if ( n == cpu )
260       continue;
261     bsp_smp_wait_for(
262       (unsigned int *)&_Per_CPU_Information[n].state,
263       RTEMS_BSP_SMP_CPU_SHUTDOWN,
264       10000
265    );
266    if ( _Per_CPU_Information[n].state != RTEMS_BSP_SMP_CPU_SHUTDOWN )
267      allDown = false;
268  }
269  if ( !allDown )
270    printk( "not all down -- timed out\n" );
271  #if defined(RTEMS_DEBUG)
272    else
273      printk( "All CPUs shutdown successfully\n" );
274  #endif
275}
Note: See TracBrowser for help on using the repository browser.