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

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

scheduler: New simple SMP scheduler implementation

The new Simple SMP Scheduler allocates a processor for the processor
count highest priority ready threads. The thread priority and position
in the ready chain are the only information to determine the scheduling
decision. Threads with an allocated processor are in the scheduled
chain. After initialization the scheduled chain has exactly processor
count nodes. Each processor has exactly one allocated thread after
initialization. All enqueue and extract operations may exchange threads
with the scheduled chain. One thread will be added and another will be
removed. The scheduled and ready chain is ordered according to the
thread priority order. The chain insert operations are O(count of ready
threads), thus this scheduler is unsuitable for most real-time
applications.

The thread preempt mode will be ignored.

  • 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  int              self = bsp_smp_processor_id();
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  int              self = bsp_smp_processor_id();
71  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ];
72  uint32_t         message;
73  ISR_Level        level;
74
75
76  _Per_CPU_Lock_acquire( per_cpu, level );
77  message = per_cpu->message;
78  per_cpu->message = 0;
79  _Per_CPU_Lock_release( per_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( "ISR on CPU %d -- (0x%02x) (0x%p)\n", self, message, sp );
86        if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY )
87          printk( "context switch necessary\n" );
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 
94      printk( "Dispatch level %d\n", _Thread_Dispatch_get_disable_level() );
95    }
96  #endif
97
98  if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
99    _ISR_Disable_on_this_core( level );
100
101    while ( _Thread_Dispatch_decrement_disable_level() != 0 ) {
102      /* Release completely */
103    }
104
105    _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_SHUTDOWN );
106
107    _CPU_Fatal_halt( self );
108    /* does not continue past here */
109  }
110}
111
112void _SMP_Send_message( int cpu, uint32_t message )
113{
114  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
115  ISR_Level level;
116
117  #if defined(RTEMS_DEBUG)
118    if ( message & RTEMS_BSP_SMP_SIGNAL_TO_SELF )
119      printk( "Send 0x%x to %d\n", message, cpu );
120  #endif
121
122  _Per_CPU_Lock_acquire( per_cpu, level );
123  per_cpu->message |= message;
124  _Per_CPU_Lock_release( per_cpu, level );
125
126  bsp_smp_interrupt_cpu( cpu );
127}
128
129void _SMP_Broadcast_message( uint32_t message )
130{
131  int self = bsp_smp_processor_id();
132  int ncpus = _SMP_Get_processor_count();
133  int cpu;
134
135  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
136    if ( cpu != self ) {
137      Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
138      ISR_Level level;
139
140      _Per_CPU_Lock_acquire( per_cpu, level );
141      per_cpu->message |= message;
142      _Per_CPU_Lock_release( per_cpu, level );
143    }
144  }
145
146  bsp_smp_broadcast_interrupt();
147}
148
149void _SMP_Request_other_cores_to_perform_first_context_switch( void )
150{
151  int self = bsp_smp_processor_id();
152  int ncpus = _SMP_Get_processor_count();
153  int cpu;
154
155  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
156    Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
157
158    if ( cpu != self ) {
159      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
160    } else {
161
162      _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP );
163    }
164  }
165}
166
167void _SMP_Request_other_cores_to_dispatch( void )
168{
169  if ( _System_state_Is_up( _System_state_Get() ) ) {
170    int self = bsp_smp_processor_id();
171    int ncpus = _SMP_Get_processor_count();
172    int cpu;
173
174    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
175      const Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
176
177      if (
178        cpu != self
179          && per_cpu->state == PER_CPU_STATE_UP
180          && per_cpu->dispatch_necessary
181      ) {
182        _SMP_Send_message( cpu, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY );
183      }
184    }
185  }
186}
187
188void _SMP_Request_other_cores_to_shutdown( void )
189{
190  int self = bsp_smp_processor_id();
191  int ncpus = _SMP_Get_processor_count();
192  int cpu;
193
194  _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN );
195
196  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
197    if ( cpu != self ) {
198      _Per_CPU_Wait_for_state(
199        &_Per_CPU_Information[ cpu ],
200        PER_CPU_STATE_SHUTDOWN
201      );
202    }
203  }
204}
Note: See TracBrowser for help on using the repository browser.