Changeset 7336be9d in rtems


Ignore:
Timestamp:
Feb 18, 2014, 12:40:39 PM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
ba25cc2
Parents:
7fe05615
git-author:
Sebastian Huber <sebastian.huber@…> (02/18/14 12:40:39)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/06/14 08:43:57)
Message:

score: SMP initialization and shutdown changes

Rename _SMP_Request_other_cores_to_perform_first_context_switch() into
_SMP_Request_start_multitasking() since this requests now a multitasking
start on all configured and available processors. The name corresponds
_Thread_Start_multitasking() and
_SMP_Start_multitasking_on_secondary_processor() actions issued in
response to this request. Move in source file to right place.

Rename PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING into
PER_CPU_STATE_READY_TO_START_MULTITASKING.

Rename PER_CPU_STATE_BEGIN_MULTITASKING into
PER_CPU_STATE_REQUEST_START_MULTITASKING.

Rename _SMP_Request_other_cores_to_shutdown() into
_SMP_Request_shutdown().

Add a per-CPU state lock to protect all changes. This was necessary to
offer a controlled shutdown of the system (atomic read/writes alone are
not sufficient for this kind of synchronization).

Add documentation for Per_CPU_State.

Delete debug output.

New tests smptests/smpfatal01 and smptests/smpfatal02.

Files:
8 added
10 edited

Legend:

Unmodified
Added
Removed
  • cpukit/sapi/src/exinit.c

    r7fe05615 r7336be9d  
    211211  _System_state_Set( SYSTEM_STATE_UP );
    212212
    213   _SMP_Request_other_cores_to_perform_first_context_switch();
     213  _SMP_Request_start_multitasking();
    214214
    215215  _Thread_Start_multitasking();
  • cpukit/score/cpu/no_cpu/rtems/score/cpu.h

    r7fe05615 r7336be9d  
    14631463#ifdef RTEMS_SMP
    14641464  /**
    1465    * @brief Performs CPU specific SMP initialization in the context of the main
     1465   * @brief Performs CPU specific SMP initialization in the context of the boot
    14661466   * processor.
    14671467   *
    1468    * This function is invoked on the main processor by RTEMS during
     1468   * This function is invoked on the boot processor by RTEMS during
    14691469   * initialization.  All interrupt stacks are allocated at this point in case
    14701470   * the CPU port allocates the interrupt stacks.
  • cpukit/score/include/rtems/score/percpu.h

    r7fe05615 r7336be9d  
    7171#endif
    7272
     73/**
     74 * @brief State of a processor.
     75 *
     76 * The processor state controls the life cycle of processors at the lowest
     77 * level.  No multi-threading or other high-level concepts matter here.
     78 *
     79 * State changes must be initiated via _Per_CPU_Change_state().  This function
     80 * may not return in case someone requested a shutdown.  The
     81 * _SMP_Send_message() function will be used to notify other processors about
     82 * state changes if the other processor is in the up state.
     83 *
     84 * Due to the sequential nature of the basic system initialization one
     85 * processor has a special role.  It is the processor executing the boot_card()
     86 * function.  This processor is called the boot processor.  All other
     87 * processors are called secondary.
     88 *
     89 * @dot
     90 * digraph states {
     91 *   i [label="PER_CPU_STATE_INITIAL"];
     92 *   rdy [label="PER_CPU_STATE_READY_TO_START_MULTITASKING"];
     93 *   reqsm [label="PER_CPU_STATE_REQUEST_START_MULTITASKING"];
     94 *   u [label="PER_CPU_STATE_UP"];
     95 *   s [label="PER_CPU_STATE_SHUTDOWN"];
     96 *   i -> rdy [label="processor\ncompleted initialization"];
     97 *   rdy -> reqsm [label="boot processor\ncompleted initialization"];
     98 *   reqsm -> u [label="processor\nstarts multitasking"];
     99 *   i -> s;
     100 *   rdy -> s;
     101 *   reqsm -> s;
     102 *   u -> s;
     103 * }
     104 * @enddot
     105 */
    73106typedef enum {
    74107  /**
    75108   * @brief The per CPU controls are initialized to zero.
    76109   *
    77    * In this state the only valid field of the per CPU controls for secondary
    78    * processors is the per CPU state.  The secondary processors should perform
    79    * their basic initialization now and change into the
    80    * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state once this is complete.
    81    *
    82    * The owner of the per CPU state field is the secondary processor in this
    83    * state.
    84    */
    85   PER_CPU_STATE_BEFORE_INITIALIZATION,
    86 
    87   /**
    88    * @brief Secondary processor is ready to begin multitasking.
     110   * The boot processor executes the sequential boot code in this state.  The
     111   * secondary processors should perform their basic initialization now and
     112   * change into the PER_CPU_STATE_READY_TO_START_MULTITASKING state once this
     113   * is complete.
     114   */
     115  PER_CPU_STATE_INITIAL,
     116
     117  /**
     118   * @brief Processor is ready to start multitasking.
    89119   *
    90120   * The secondary processor performed its basic initialization and is ready to
     
    92122   * in this state, but requested inter-processor interrupts must be recorded
    93123   * and must be delivered once the secondary processor enables interrupts for
    94    * the first time.  The main processor will wait for all secondary processors
     124   * the first time.  The boot processor will wait for all secondary processors
    95125   * to change into this state.  In case a secondary processor does not reach
    96126   * this state the system will not start.  The secondary processors wait now
    97    * for a change into the PER_CPU_STATE_BEGIN_MULTITASKING state set by the
    98    * main processor once all secondary processors reached the
    99    * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state.
     127   * for a change into the PER_CPU_STATE_REQUEST_START_MULTITASKING state set
     128   * by the boot processor once all secondary processors reached the
     129   * PER_CPU_STATE_READY_TO_START_MULTITASKING state.
     130   */
     131  PER_CPU_STATE_READY_TO_START_MULTITASKING,
     132
     133  /**
     134   * @brief Multitasking start of processor is requested.
    100135   *
    101    * The owner of the per CPU state field is the main processor in this state.
    102    */
    103   PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING,
    104 
    105   /**
    106    * @brief Multitasking begin of secondary processor is requested.
    107    *
    108    * The main processor completed system initialization and is about to perform
     136   * The boot processor completed system initialization and is about to perform
    109137   * a context switch to its heir thread.  Secondary processors should now
    110138   * issue a context switch to the heir thread.  This normally enables
    111139   * interrupts on the processor for the first time.
    112    *
    113    * The owner of the per CPU state field is the secondary processor in this
    114    * state.
    115    */
    116   PER_CPU_STATE_BEGIN_MULTITASKING,
     140   */
     141  PER_CPU_STATE_REQUEST_START_MULTITASKING,
    117142
    118143  /**
    119144   * @brief Normal multitasking state.
    120    *
    121    * The owner of the per CPU state field is the secondary processor in this
    122    * state.
    123145   */
    124146  PER_CPU_STATE_UP,
     
    126148  /**
    127149   * @brief This is the terminal state.
    128    *
    129    * The owner of the per CPU state field is the secondary processor in this
    130    * state.
    131150   */
    132151  PER_CPU_STATE_SHUTDOWN
     
    314333void _Per_CPU_Initialize(void);
    315334
    316 void _Per_CPU_Change_state(
     335void _Per_CPU_State_change(
    317336  Per_CPU_Control *per_cpu,
    318337  Per_CPU_State new_state
    319 );
    320 
    321 void _Per_CPU_Wait_for_state(
    322   const Per_CPU_Control *per_cpu,
    323   Per_CPU_State desired_state
    324338);
    325339
  • cpukit/score/include/rtems/score/smpimpl.h

    r7fe05615 r7336be9d  
    109109
    110110    if ( ( message & SMP_MESSAGE_SHUTDOWN ) != 0 ) {
    111       _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_SHUTDOWN );
    112 
    113111      rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
    114112      /* does not continue past here */
     
    144142
    145143/**
    146  *  @brief Request other cores to perform first context switch.
    147  *
    148  *  Send message to other cores requesting them to perform
    149  *  their first context switch operation.
     144 * @brief Requests a multitasking start on all configured and available
     145 * processors.
    150146 */
    151147#if defined( RTEMS_SMP )
    152   void _SMP_Request_other_cores_to_perform_first_context_switch( void );
     148  void _SMP_Request_start_multitasking( void );
    153149#else
    154   #define _SMP_Request_other_cores_to_perform_first_context_switch() \
     150  #define _SMP_Request_start_multitasking() \
    155151    do { } while ( 0 )
    156152#endif
    157153
    158154/**
    159  *  @brief Request other cores to shutdown.
     155 * @brief Requests a shutdown of all processors.
    160156 *
    161  *  Send message to other cores requesting them to shutdown.
     157 * This function is a part of the system termination procedure.
     158 *
     159 * @see _Terminate().
    162160 */
    163161#if defined( RTEMS_SMP )
    164   void _SMP_Request_other_cores_to_shutdown( void );
     162  void _SMP_Request_shutdown( void );
    165163#else
    166   #define _SMP_Request_other_cores_to_shutdown() \
     164  #define _SMP_Request_shutdown() \
    167165    do { } while ( 0 )
    168166#endif
  • cpukit/score/src/interr.c

    r7fe05615 r7336be9d  
    4040  (void) level;
    4141
    42   _SMP_Request_other_cores_to_shutdown();
     42  _SMP_Request_shutdown();
    4343
    4444  _User_extensions_Fatal( the_source, is_internal, the_error );
  • cpukit/score/src/percpu.c

    r7fe05615 r7336be9d  
    2020
    2121#include <rtems/score/percpu.h>
     22#include <rtems/score/assert.h>
     23#include <rtems/score/smpimpl.h>
     24#include <rtems/config.h>
     25#include <rtems/fatal.h>
    2226
    2327#if defined(RTEMS_SMP)
    24   void _Per_CPU_Change_state(
    25     Per_CPU_Control *per_cpu,
    26     Per_CPU_State new_state
    27   )
    28   {
    29     per_cpu->state = new_state;
    30     _CPU_SMP_Processor_event_broadcast();
     28
     29static SMP_lock_Control _Per_CPU_State_lock = SMP_LOCK_INITIALIZER;
     30
     31static ISR_Level _Per_CPU_State_acquire( void )
     32{
     33  ISR_Level level;
     34
     35  _SMP_lock_ISR_disable_and_acquire( &_Per_CPU_State_lock, level );
     36
     37  return level;
     38}
     39
     40static void _Per_CPU_State_release( ISR_Level level )
     41{
     42  _SMP_lock_Release_and_ISR_enable( &_Per_CPU_State_lock, level );
     43}
     44
     45static void _Per_CPU_State_busy_wait(
     46  const Per_CPU_Control *per_cpu,
     47  Per_CPU_State new_state
     48)
     49{
     50  Per_CPU_State state = per_cpu->state;
     51
     52  switch ( new_state ) {
     53    case PER_CPU_STATE_REQUEST_START_MULTITASKING:
     54      while (
     55        state != PER_CPU_STATE_READY_TO_START_MULTITASKING
     56          && state != PER_CPU_STATE_SHUTDOWN
     57      ) {
     58        _CPU_SMP_Processor_event_receive();
     59        state = per_cpu->state;
     60      }
     61      break;
     62    case PER_CPU_STATE_UP:
     63      while (
     64        state != PER_CPU_STATE_REQUEST_START_MULTITASKING
     65          && state != PER_CPU_STATE_SHUTDOWN
     66      ) {
     67        _CPU_SMP_Processor_event_receive();
     68        state = per_cpu->state;
     69      }
     70      break;
     71    default:
     72      /* No need to wait */
     73      break;
     74  }
     75}
     76
     77static Per_CPU_State _Per_CPU_State_get_next(
     78  Per_CPU_State current_state,
     79  Per_CPU_State new_state
     80)
     81{
     82  switch ( current_state ) {
     83    case PER_CPU_STATE_INITIAL:
     84      switch ( new_state ) {
     85        case PER_CPU_STATE_READY_TO_START_MULTITASKING:
     86        case PER_CPU_STATE_SHUTDOWN:
     87          /* Change is acceptable */
     88          break;
     89        default:
     90          new_state = PER_CPU_STATE_SHUTDOWN;
     91          break;
     92      }
     93      break;
     94    case PER_CPU_STATE_READY_TO_START_MULTITASKING:
     95      switch ( new_state ) {
     96        case PER_CPU_STATE_REQUEST_START_MULTITASKING:
     97        case PER_CPU_STATE_SHUTDOWN:
     98          /* Change is acceptable */
     99          break;
     100        default:
     101          new_state = PER_CPU_STATE_SHUTDOWN;
     102          break;
     103      }
     104      break;
     105    case PER_CPU_STATE_REQUEST_START_MULTITASKING:
     106      switch ( new_state ) {
     107        case PER_CPU_STATE_UP:
     108        case PER_CPU_STATE_SHUTDOWN:
     109          /* Change is acceptable */
     110          break;
     111        default:
     112          new_state = PER_CPU_STATE_SHUTDOWN;
     113          break;
     114      }
     115      break;
     116    default:
     117      new_state = PER_CPU_STATE_SHUTDOWN;
     118      break;
    31119  }
    32120
    33   void _Per_CPU_Wait_for_state(
    34     const Per_CPU_Control *per_cpu,
    35     Per_CPU_State desired_state
    36   )
    37   {
    38     while ( per_cpu->state != desired_state ) {
    39       _CPU_SMP_Processor_event_receive();
     121  return new_state;
     122}
     123
     124void _Per_CPU_State_change(
     125  Per_CPU_Control *per_cpu,
     126  Per_CPU_State new_state
     127)
     128{
     129  ISR_Level level;
     130  Per_CPU_State next_state;
     131
     132  _Per_CPU_State_busy_wait( per_cpu, new_state );
     133
     134  level = _Per_CPU_State_acquire();
     135  next_state = _Per_CPU_State_get_next( per_cpu->state, new_state );
     136  per_cpu->state = next_state;
     137
     138  if ( next_state == PER_CPU_STATE_SHUTDOWN ) {
     139    uint32_t ncpus = rtems_configuration_get_maximum_processors();
     140    uint32_t cpu;
     141
     142    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     143      Per_CPU_Control *other_cpu = _Per_CPU_Get_by_index( cpu );
     144
     145      if ( per_cpu != other_cpu ) {
     146        switch ( other_cpu->state ) {
     147          case PER_CPU_STATE_UP:
     148            _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
     149            break;
     150          default:
     151            /* Nothing to do */
     152            break;
     153        }
     154
     155        other_cpu->state = PER_CPU_STATE_SHUTDOWN;
     156      }
    40157    }
    41158  }
     159
     160  _CPU_SMP_Processor_event_broadcast();
     161
     162  _Per_CPU_State_release( level );
     163
     164  if (
     165    next_state == PER_CPU_STATE_SHUTDOWN
     166      && new_state != PER_CPU_STATE_SHUTDOWN
     167  ) {
     168    rtems_fatal( RTEMS_FATAL_SOURCE_SMP, SMP_FATAL_SHUTDOWN );
     169  }
     170}
     171
    42172#else
    43173  /*
  • cpukit/score/src/smp.c

    r7fe05615 r7336be9d  
    2525#include <rtems/config.h>
    2626
    27 #if defined(RTEMS_DEBUG)
    28   #include <rtems/bspIo.h>
    29 #endif
    30 
    3127void _SMP_Handler_initialize( void )
    3228{
     
    4844}
    4945
     46void _SMP_Request_start_multitasking( void )
     47{
     48  Per_CPU_Control *self_cpu = _Per_CPU_Get();
     49  uint32_t ncpus = _SMP_Get_processor_count();
     50  uint32_t cpu;
     51
     52  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
     53
     54  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     55    Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
     56
     57    _Per_CPU_State_change( per_cpu, PER_CPU_STATE_REQUEST_START_MULTITASKING );
     58  }
     59}
     60
    5061void _SMP_Start_multitasking_on_secondary_processor( void )
    5162{
    5263  Per_CPU_Control *self_cpu = _Per_CPU_Get();
    5364
    54   #if defined(RTEMS_DEBUG)
    55     printk( "Made it to %d -- ", _Per_CPU_Get_index( self_cpu ) );
    56   #endif
    57 
    58   _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
    59 
    60   _Per_CPU_Wait_for_state( self_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
     65  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_READY_TO_START_MULTITASKING );
    6166
    6267  _Thread_Start_multitasking();
     68}
     69
     70void _SMP_Request_shutdown( void )
     71{
     72  uint32_t self = _SMP_Get_current_processor();
     73  Per_CPU_Control *self_cpu = _Per_CPU_Get_by_index( self );
     74
     75  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_SHUTDOWN );
    6376}
    6477
     
    89102  }
    90103}
    91 
    92 void _SMP_Request_other_cores_to_perform_first_context_switch( void )
    93 {
    94   uint32_t self = _SMP_Get_current_processor();
    95   uint32_t ncpus = _SMP_Get_processor_count();
    96   uint32_t cpu;
    97 
    98   for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
    99     Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
    100 
    101     if ( cpu != self ) {
    102       _Per_CPU_Wait_for_state(
    103         per_cpu,
    104         PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
    105       );
    106 
    107       _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
    108     }
    109   }
    110 }
    111 
    112 void _SMP_Request_other_cores_to_shutdown( void )
    113 {
    114   uint32_t self = _SMP_Get_current_processor();
    115 
    116   /*
    117    * Do not use _SMP_Get_processor_count() since this value might be not
    118    * initialized yet.  For example due to a fatal error in the middle of
    119    * _CPU_SMP_Initialize().
    120    */
    121   uint32_t ncpus = rtems_configuration_get_maximum_processors();
    122 
    123   uint32_t cpu;
    124 
    125   for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
    126     if ( cpu != self ) {
    127       const Per_CPU_Control *per_cpu = _Per_CPU_Get_by_index( cpu );
    128 
    129       if ( per_cpu->state != PER_CPU_STATE_BEFORE_INITIALIZATION ) {
    130         _SMP_Send_message( cpu, SMP_MESSAGE_SHUTDOWN );
    131       }
    132     }
    133   }
    134 }
  • cpukit/score/src/threadstartmultitasking.c

    r7fe05615 r7336be9d  
    2727
    2828#if defined(RTEMS_SMP)
    29   _Per_CPU_Change_state( self_cpu, PER_CPU_STATE_UP );
     29  _Per_CPU_State_change( self_cpu, PER_CPU_STATE_UP );
    3030
    3131  /*
  • testsuites/smptests/Makefile.am

    r7fe05615 r7336be9d  
    1212SUBDIRS += smp09
    1313SUBDIRS += smpatomic01
     14SUBDIRS += smpfatal01
     15SUBDIRS += smpfatal02
    1416SUBDIRS += smplock01
    1517SUBDIRS += smpmigration01
  • testsuites/smptests/configure.ac

    r7fe05615 r7336be9d  
    6666smp09/Makefile
    6767smpatomic01/Makefile
     68smpfatal01/Makefile
     69smpfatal02/Makefile
    6870smplock01/Makefile
    6971smpmigration01/Makefile
Note: See TracChangeset for help on using the changeset viewer.