source: rtems/cpukit/score/src/smp.c @ 21ff802

4.115
Last change on this file since 21ff802 was 21ff802, checked in by Sebastian Huber <sebastian.huber@…>, on 07/26/13 at 14:26:07

smp: Delete _ISR_Disable_on_this_core(), etc.

Delete _ISR_Enable_on_this_core(), _ISR_Flash_on_this_core(),
_ISR_SMP_Disable(), _ISR_SMP_Enable(), _ISR_SMP_Flash().

The ISR disable/enable interface has no parameter to pass a specific
object. Thus it is only possible to implement a single global lock
object with this interface. Using the ISR disable/enable as the giant
lock on SMP configurations is not feasible.

Potentially blocking resource obtain sequences protected by the thread
dispatch disable level are subdivided into smaller ISR disabled critical
sections. This works since on single processor configurations there is
only one thread of execution that can block. On SMP this is different
(image a mutex obtained concurrently by different threads on different
processors).

The thread dispatch disable level is currently used as the giant lock.
There is not need to complicate things with this unused interface.

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