source: rtems/cpukit/score/src/smp.c @ 8cacceb

4.115
Last change on this file since 8cacceb was 8cacceb, checked in by Sebastian Huber <sebastian.huber@…>, on May 14, 2013 at 11:23:10 AM

smp: Delete bsp_smp_secondary_cpu_initialize()

Do not call bsp_smp_secondary_cpu_initialize() in
rtems_smp_secondary_cpu_initialize(). This allows more flexibilty in
the BSP low-level code. Specify context requirements for a call to
rtems_smp_secondary_cpu_initialize().

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