source: rtems/cpukit/score/src/smp.c @ e6f7f81

4.115
Last change on this file since e6f7f81 was ca63ae2, checked in by Sebastian Huber <sebastian.huber@…>, on 06/13/13 at 13:41:21

smp: Add and use _CPU_SMP_Send_interrupt()

Delete bsp_smp_interrupt_cpu().

  • Property mode set to 100644
File size: 5.1 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#include <rtems/score/threaddispatch.h>
26
27#if defined(RTEMS_DEBUG)
28  #include <rtems/bspIo.h>
29#endif
30
31void rtems_smp_secondary_cpu_initialize( void )
32{
33  uint32_t         self = _SMP_Get_current_processor();
34  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ];
35  Thread_Control  *heir;
36
37  #if defined(RTEMS_DEBUG)
38    printk( "Made it to %d -- ", self );
39  #endif
40
41  _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
42
43  _Per_CPU_Wait_for_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
44
45  _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP );
46
47  /*
48   *  The Scheduler will have selected the heir thread for each CPU core.
49   *  Now we have been requested to perform the first context switch.  So
50   *  force a switch to the designated heir and make it executing on
51   *  THIS core.
52   */
53  heir = per_cpu->heir;
54  heir->is_executing = true;
55  per_cpu->executing->is_executing = false;
56  per_cpu->executing = heir;
57  per_cpu->dispatch_necessary = false;
58
59  /*
60   * Threads begin execution in the _Thread_Handler() function.   This function
61   * will call _Thread_Enable_dispatch().
62   */
63  _Thread_Disable_dispatch();
64
65  _CPU_Context_switch_to_first_task_smp( &heir->Registers );
66}
67
68void rtems_smp_process_interrupt( void )
69{
70  uint32_t         self = _SMP_Get_current_processor();
71  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ];
72
73
74  if ( per_cpu->message != 0 ) {
75    uint32_t  message;
76    ISR_Level level;
77
78    _Per_CPU_Lock_acquire( per_cpu, level );
79    message = per_cpu->message;
80    per_cpu->message = 0;
81    _Per_CPU_Lock_release( per_cpu, level );
82
83    #if defined(RTEMS_DEBUG)
84      {
85        void *sp = __builtin_frame_address(0);
86        if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) {
87          printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", self, message, sp );
88          if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
89            printk( "signal to self\n" );
90          if ( message & RTEMS_BSP_SMP_SHUTDOWN )
91            printk( "shutdown\n" );
92        }
93        printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
94      }
95    #endif
96
97    if ( ( message & RTEMS_BSP_SMP_SHUTDOWN ) != 0 ) {
98      _ISR_Disable_on_this_core( level );
99
100      _Thread_Dispatch_set_disable_level( 0 );
101
102      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_SHUTDOWN );
103
104      _CPU_Fatal_halt( self );
105      /* does not continue past here */
106    }
107  }
108}
109
110void _SMP_Send_message( uint32_t cpu, uint32_t message )
111{
112  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
113  ISR_Level level;
114
115  #if defined(RTEMS_DEBUG)
116    if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
117      printk( "Send 0x%x to %d\n", message, cpu );
118  #endif
119
120  _Per_CPU_Lock_acquire( per_cpu, level );
121  per_cpu->message |= message;
122  _Per_CPU_Lock_release( per_cpu, level );
123
124  _CPU_SMP_Send_interrupt( cpu );
125}
126
127void _SMP_Broadcast_message( uint32_t message )
128{
129  uint32_t self = _SMP_Get_current_processor();
130  uint32_t ncpus = _SMP_Get_processor_count();
131  uint32_t cpu;
132
133  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
134    if ( cpu != self ) {
135      Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
136      ISR_Level level;
137
138      _Per_CPU_Lock_acquire( per_cpu, level );
139      per_cpu->message |= message;
140      _Per_CPU_Lock_release( per_cpu, level );
141    }
142  }
143
144  bsp_smp_broadcast_interrupt();
145}
146
147void _SMP_Request_other_cores_to_perform_first_context_switch( void )
148{
149  uint32_t self = _SMP_Get_current_processor();
150  uint32_t ncpus = _SMP_Get_processor_count();
151  uint32_t cpu;
152
153  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
154    Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
155
156    if ( cpu != self ) {
157      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
158    } else {
159
160      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP );
161    }
162  }
163}
164
165void _SMP_Request_other_cores_to_dispatch( void )
166{
167  if ( _System_state_Is_up( _System_state_Get() ) ) {
168    uint32_t self = _SMP_Get_current_processor();
169    uint32_t ncpus = _SMP_Get_processor_count();
170    uint32_t cpu;
171
172    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
173      const Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
174
175      if (
176        cpu != self
177          && per_cpu->state == PER_CPU_STATE_UP
178          && per_cpu->dispatch_necessary
179      ) {
180        _SMP_Send_message( cpu, 0 );
181      }
182    }
183  }
184}
185
186void _SMP_Request_other_cores_to_shutdown( void )
187{
188  uint32_t self = _SMP_Get_current_processor();
189  uint32_t ncpus = _SMP_Get_processor_count();
190  uint32_t cpu;
191
192  _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN );
193
194  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
195    if ( cpu != self ) {
196      _Per_CPU_Wait_for_state(
197        &_Per_CPU_Information[ cpu ],
198        PER_CPU_STATE_SHUTDOWN
199      );
200    }
201  }
202}
Note: See TracBrowser for help on using the repository browser.