Changeset 2f6108f9 in rtems


Ignore:
Timestamp:
May 28, 2013, 8:58:19 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
3148438
Parents:
8cacceb
git-author:
Sebastian Huber <sebastian.huber@…> (05/28/13 08:58:19)
git-committer:
Sebastian Huber <sebastian.huber@…> (05/29/13 09:06:07)
Message:

smp: Simplify SMP initialization sequence

Delete bsp_smp_wait_for(). Other parts of the system work without
timeout, e.g. the spinlocks. Using a timeout here does not make the
system more robust.

Delete bsp_smp_cpu_state and replace it with Per_CPU_State. The
Per_CPU_State follows the Score naming conventions. Add
_Per_CPU_Change_state() and _Per_CPU_Wait_for_state() functions to
change and observe states.

Use Per_CPU_State in Per_CPU_Control instead of the anonymous integer.

Add _CPU_Processor_event_broadcast() and _CPU_Processor_event_receive()
functions provided by the CPU port. Use these functions in
_Per_CPU_Change_state() and _Per_CPU_Wait_for_state().

Add prototype for _SMP_Send_message().

Delete RTEMS_BSP_SMP_FIRST_TASK message. The first context switch is
now performed in rtems_smp_secondary_cpu_initialize(). Issuing the
first context switch in the context of the inter-processor interrupt is
not possible on systems with a modern interrupt controller. Such an
interrupt controler usually requires a handshake protocol with interrupt
acknowledge and end of interrupt signals. A direct context switch in an
interrupt handler circumvents the interrupt processing epilogue and may
leave the system in an inconsistent state.

Release lock in rtems_smp_process_interrupt() even if no message was
delivered. This prevents deadlock of the system.

Simplify and format _SMP_Send_message(),
_SMP_Request_other_cores_to_perform_first_context_switch(),
_SMP_Request_other_cores_to_dispatch() and
_SMP_Request_other_cores_to_shutdown().

Files:
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/i386/shared/smp/smp-imps.c

    r8cacceb r2f6108f9  
    7272#define VIRTUAL_TO_PHYS(x)    /* convert virtual address "x" to physical */
    7373#define UDELAY(x)             /* delay roughly at least "x" microsecs */
    74 #define TEST_BOOTED(x)        /* test bootaddr x to see if CPU started */
    7574#define READ_MSR_LO(x)        /* Read MSR low function */
    7675#else
     
    125124#define READ_MSR_LO(_x) \
    126125  (unsigned int)(read_msr(_x) & 0xffffffff)
    127 
    128 #define TEST_BOOTED(_cpu) \
    129   (_Per_CPU_Information[_cpu].state == RTEMS_BSP_SMP_CPU_INITIALIZED)
    130126
    131127static inline unsigned long long read_msr(unsigned int msr)
     
    312308
    313309  /*
    314    *  Check to see if other processor has started.
    315    */
    316   bsp_smp_wait_for(
    317     (volatile unsigned int *)&_Per_CPU_Information[imps_num_cpus].state,
    318     RTEMS_BSP_SMP_CPU_INITIALIZED,
    319     1600
    320   );
    321   if ( _Per_CPU_Information[imps_num_cpus].state ==
    322         RTEMS_BSP_SMP_CPU_INITIALIZED )
    323     printk("#%d  Application Processor (AP)", imps_num_cpus);
    324   else {
    325     printk("CPU Not Responding, DISABLED");
    326     success = 0;
    327   }
    328 
    329   /*
    330310   *  Generic CPU startup sequence ends here, the rest is cleanup.
    331311   */
     
    836816  send_ipi( 0, LAPIC_ICR_DS_ALLEX | 0x30 );
    837817}
    838 
    839 void bsp_smp_wait_for(
    840   volatile unsigned int *address,
    841   unsigned int           desired,
    842   int                    maximum_usecs
    843 )
    844 {
    845   int iterations;
    846   volatile int i;
    847   volatile unsigned int *p = (volatile unsigned int *)address;
    848 
    849   for (iterations=0 ;  iterations < maximum_usecs ; iterations++ ) {
    850     if ( *p == desired )
    851       break;
    852     #ifdef __SSE3__
    853       __builtin_ia32_monitor( (const void *)address, 0, 0 );
    854       if ( *p == desired )
    855         break;
    856       __builtin_ia32_mwait( 0, 0 );
    857     #endif
    858 
    859     /*
    860      *  Until i386 ms delay does not depend upon the clock we
    861      *  will use this less sophisticated delay.
    862      */
    863     for(i=5000; i>0; i--)
    864       ;
    865   }
    866 }
  • c/src/lib/libbsp/sparc/erc32/Makefile.am

    r8cacceb r2f6108f9  
    6767
    6868if HAS_SMP
    69 libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \
    70     ../../shared/smp/bspsmp_wait_for.c
     69libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c
    7170endif
    7271
  • c/src/lib/libbsp/sparc/leon2/Makefile.am

    r8cacceb r2f6108f9  
    120120
    121121if HAS_SMP
    122 libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c \
    123     ../../shared/smp/bspsmp_wait_for.c
     122libbsp_a_SOURCES += ../../shared/smp/getcpuid.c ../../shared/smp/smp_stub.c
    124123endif
    125124
  • c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c

    r8cacceb r2f6108f9  
    3434}
    3535
    36 rtems_isr bsp_ap_ipi_isr(
     36static rtems_isr bsp_ap_ipi_isr(
    3737  rtems_vector_number vector
    3838)
     
    100100    #if defined(RTEMS_DEBUG)
    101101      printk(
    102         "CPU %d is %s\n",
    103         cpu,
    104         ((_Per_CPU_Information[cpu].state == RTEMS_BSP_SMP_CPU_INITIALIZED) ?
    105            "online" : "offline")
     102        "CPU %d is %s\n",
     103        cpu,
     104        _Per_CPU_Information[cpu].state
     105          == PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING ?
     106            "online" : "offline"
    106107      );
    107108    #endif
     
    161162   __delay( max );
    162163}
    163 
    164 void bsp_smp_wait_for(
    165   volatile unsigned int *address,
    166   unsigned int           desired,
    167   int                    maximum_usecs
    168 )
    169 {
    170   int iterations;
    171   volatile unsigned int *p = address;
    172 
    173   for (iterations=0 ;  iterations < maximum_usecs ; iterations++ ) {
    174     if ( *p == desired )
    175       break;
    176     bsp_smp_delay( 5000 );
    177   }
    178 }
    179 
    180 
  • cpukit/score/cpu/i386/rtems/score/cpu.h

    r8cacceb r2f6108f9  
    464464        "cc"); \
    465465    } while (0)
     466
     467  static inline void _CPU_Processor_event_broadcast( void )
     468  {
     469    __asm__ volatile ( "" : : : "memory" );
     470  }
     471
     472  static inline void _CPU_Processor_event_receive( void )
     473  {
     474    __asm__ volatile ( "" : : : "memory" );
     475  }
    466476#endif
    467477
  • cpukit/score/cpu/no_cpu/rtems/score/cpu.h

    r8cacceb r2f6108f9  
    14031403  (((value&0xff) << 8) | ((value >> 8)&0xff))
    14041404
     1405#ifdef RTEMS_SMP
     1406  /**
     1407   * @brief Broadcasts a processor event.
     1408   *
     1409   * Some architectures provide a low-level synchronization primitive for
     1410   * processors in a multi-processor environment.  Processors waiting for this
     1411   * event may go into a low-power state and stop generating system bus
     1412   * transactions.  This function must ensure that preceding store operations
     1413   * can be observed by other processors.
     1414   *
     1415   * @see _CPU_Processor_event_receive().
     1416   */
     1417  static inline void _CPU_Processor_event_broadcast( void )
     1418  {
     1419    __asm__ volatile ( "" : : : "memory" );
     1420  }
     1421
     1422  /**
     1423   * @brief Receives a processor event.
     1424   *
     1425   * This function will wait for the processor event and may wait forever if no
     1426   * such event arrives.
     1427   *
     1428   * @see _CPU_Processor_event_broadcast().
     1429   */
     1430  static inline void _CPU_Processor_event_receive( void )
     1431  {
     1432    __asm__ volatile ( "" : : : "memory" );
     1433  }
     1434#endif
     1435
    14051436#ifdef __cplusplus
    14061437}
  • cpukit/score/cpu/sparc/rtems/score/cpu.h

    r8cacceb r2f6108f9  
    12041204      _previous = _val; \
    12051205    } while (0)
     1206
     1207  static inline void _CPU_Processor_event_broadcast( void )
     1208  {
     1209    __asm__ volatile ( "" : : : "memory" );
     1210  }
     1211
     1212  static inline void _CPU_Processor_event_receive( void )
     1213  {
     1214    __asm__ volatile ( "" : : : "memory" );
     1215  }
    12061216#endif
    12071217
  • cpukit/score/include/rtems/bspsmp.h

    r8cacceb r2f6108f9  
    149149void rtems_smp_process_interrupt(void);
    150150
    151 void bsp_smp_wait_for(
    152   volatile unsigned int *address,
    153   unsigned int           desired,
    154   int                    maximum_usecs
    155 );
    156 
    157151#endif
    158152
  • cpukit/score/include/rtems/score/percpu.h

    r8cacceb r2f6108f9  
    6161#endif
    6262
     63#ifdef RTEMS_SMP
     64
    6365typedef enum {
    64 
    65   /**
    66    *  This defines the constant used to indicate that the cpu code is in
    67    *  its initial powered up start.
    68    */
    69    RTEMS_BSP_SMP_CPU_INITIAL_STATE = 1,
    70 
    71   /**
    72    *  This defines the constant used to indicate that the cpu code has
    73    *  completed basic initialization and awaits further commands.
    74    */
    75    RTEMS_BSP_SMP_CPU_INITIALIZED = 2,
    76 
    77   /**
    78    *  This defines the constant used to indicate that the cpu code has
    79    *  completed basic initialization and awaits further commands.
    80    */
    81   RTEMS_BSP_SMP_CPU_UP = 3,
    82 
    83   /**
    84    *  This defines the constant used to indicate that the cpu code has
    85    *  shut itself down.
    86    */
    87   RTEMS_BSP_SMP_CPU_SHUTDOWN = 4
    88 } bsp_smp_cpu_state;
     66  /**
     67   * @brief The per CPU controls are initialized to zero.
     68   *
     69   * In this state the only valid field of the per CPU controls for secondary
     70   * processors is the per CPU state.  The secondary processors should perform
     71   * their basic initialization now and change into the
     72   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state once this is complete.
     73   *
     74   * The owner of the per CPU state field is the secondary processor in this
     75   * state.
     76   */
     77  PER_CPU_STATE_BEFORE_INITIALIZATION,
     78
     79  /**
     80   * @brief Secondary processor is ready to begin multitasking.
     81   *
     82   * The secondary processor performed its basic initialization and is ready to
     83   * receive inter-processor interrupts.  Interrupt delivery must be disabled
     84   * in this state, but requested inter-processor interrupts must be recorded
     85   * and must be delivered once the secondary processor enables interrupts for
     86   * the first time.  The main processor will wait for all secondary processors
     87   * to change into this state.  In case a secondary processor does not reach
     88   * this state the system will not start.  The secondary processors wait now
     89   * for a change into the PER_CPU_STATE_BEGIN_MULTITASKING state set by the
     90   * main processor once all secondary processors reached the
     91   * PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING state.
     92   *
     93   * The owner of the per CPU state field is the main processor in this state.
     94   */
     95  PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING,
     96
     97  /**
     98   * @brief Multitasking begin of secondary processor is requested.
     99   *
     100   * The main processor completed system initialization and is about to perform
     101   * a context switch to its heir thread.  Secondary processors should now
     102   * issue a context switch to the heir thread.  This normally enables
     103   * interrupts on the processor for the first time.
     104   *
     105   * The owner of the per CPU state field is the secondary processor in this
     106   * state.
     107   */
     108  PER_CPU_STATE_BEGIN_MULTITASKING,
     109
     110  /**
     111   * @brief Normal multitasking state.
     112   *
     113   * The owner of the per CPU state field is the secondary processor in this
     114   * state.
     115   */
     116  PER_CPU_STATE_UP,
     117
     118  /**
     119   * @brief This is the terminal state.
     120   *
     121   * The owner of the per CPU state field is the secondary processor in this
     122   * state.
     123   */
     124  PER_CPU_STATE_SHUTDOWN
     125} Per_CPU_State;
     126
     127#endif /* RTEMS_SMP */
    89128
    90129/**
     
    134173    SMP_lock_spinlock_simple_Control  lock;
    135174
    136     /** This indicates that the CPU is online. */
    137     uint32_t                          state;
    138 
    139175    /**
    140176     *  This is the request for the interrupt.
     
    142178     *  @note This may become a chain protected by atomic instructions.
    143179     */
    144     uint32_t                          message;
     180    uint32_t message;
     181
     182    /**
     183     * @brief Indicates the current state of the CPU.
     184     *
     185     * This field is not protected by a lock.
     186     *
     187     * @see _Per_CPU_Change_state() and _Per_CPU_Wait_for_state().
     188     */
     189    Per_CPU_State state;
    145190  #endif
    146191} Per_CPU_Control;
     
    218263 */
    219264void _Per_CPU_Initialize(void);
     265
     266void _Per_CPU_Change_state(
     267  Per_CPU_Control *per_cpu,
     268  Per_CPU_State new_state
     269);
     270
     271void _Per_CPU_Wait_for_state(
     272  const Per_CPU_Control *per_cpu,
     273  Per_CPU_State desired_state
     274);
    220275
    221276#endif
  • cpukit/score/include/rtems/score/smp.h

    r8cacceb r2f6108f9  
    5959#define RTEMS_BSP_SMP_SHUTDOWN                  0x04
    6060
    61 /**
    62  *  This defines the bit which indicates the interprocessor interrupt
    63  *  has been requested that the receiving CPU needs to perform a context
    64  *  switch to the first task.
    65  */
    66 #define RTEMS_BSP_SMP_FIRST_TASK                0x08
    67 
    6861#ifndef ASM
    6962/**
     
    7467 */
    7568SCORE_EXTERN uint32_t _SMP_Processor_count;
     69
     70/**
     71 *  @brief Sends a SMP message to a processor.
     72 *
     73 *  The target processor may be the sending processor.
     74 *
     75 *  @param[in] cpu The target processor of the message.
     76 *  @param[in] message The message.
     77 */
     78void _SMP_Send_message( int cpu, uint32_t message );
    7679
    7780/**
  • cpukit/score/src/percpu.c

    r8cacceb r2f6108f9  
    5757      }
    5858#endif
    59 
    60       p->state = RTEMS_BSP_SMP_CPU_INITIAL_STATE;
    61       RTEMS_COMPILER_MEMORY_BARRIER();
    6259    }
    6360
     
    6865
    6966    _SMP_Processor_count = max_cpus;
     67
     68    for ( cpu = 1 ; cpu < max_cpus; ++cpu ) {
     69      _Per_CPU_Wait_for_state(
     70        &_Per_CPU_Information[ cpu ],
     71        PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING
     72      );
     73    }
     74  }
     75
     76  void _Per_CPU_Change_state(
     77    Per_CPU_Control *per_cpu,
     78    Per_CPU_State new_state
     79  )
     80  {
     81    per_cpu->state = new_state;
     82    _CPU_Processor_event_broadcast();
     83  }
     84
     85  void _Per_CPU_Wait_for_state(
     86    const Per_CPU_Control *per_cpu,
     87    Per_CPU_State desired_state
     88  )
     89  {
     90    while ( per_cpu->state != desired_state ) {
     91      _CPU_Processor_event_receive();
     92    }
    7093  }
    7194#else
  • cpukit/score/src/smp.c

    r8cacceb r2f6108f9  
    2828#endif
    2929
    30 /*
    31  *  Process request to switch to the first task on a secondary core.
    32  */
    33 void rtems_smp_run_first_task(int cpu)
     30void rtems_smp_secondary_cpu_initialize( void )
    3431{
    35   Thread_Control *heir;
    36   ISR_Level       level;
     32  int              self = bsp_smp_processor_id();
     33  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ];
     34  Thread_Control  *heir;
    3735
    38   _ISR_Disable_on_this_core( level );
     36  #if defined(RTEMS_DEBUG)
     37    printk( "Made it to %d -- ", self );
     38  #endif
     39
     40  _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_READY_TO_BEGIN_MULTITASKING );
     41
     42  _Per_CPU_Wait_for_state( per_cpu, PER_CPU_STATE_BEGIN_MULTITASKING );
     43
     44  _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_UP );
    3945
    4046  /*
    4147   *  The Scheduler will have selected the heir thread for each CPU core.
    4248   *  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 
     49   *  force a switch to the designated heir and make it executing on
    4450   *  THIS core.
    4551   */
    46   heir              = _Thread_Heir;
    47   _Thread_Executing = heir;
     52  heir = per_cpu->heir;
     53  per_cpu->executing = heir;
     54
     55  /*
     56   * Threads begin execution in the _Thread_Handler() function.   This function
     57   * will call _Thread_Enable_dispatch().
     58   */
     59  _Thread_Disable_dispatch();
    4860
    4961  _CPU_Context_switch_to_first_task_smp( &heir->Registers );
    5062}
    5163
    52 void rtems_smp_secondary_cpu_initialize(void)
     64void rtems_smp_process_interrupt( void )
    5365{
    54   int       cpu;
    55   ISR_Level level;
     66  int              self = bsp_smp_processor_id();
     67  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ self ];
     68  uint32_t         message;
     69  ISR_Level        level;
    5670
    57   cpu = bsp_smp_processor_id();
    5871
    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 
    94 void 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;
     72  level = _SMP_lock_spinlock_simple_Obtain( &per_cpu->lock );
     73  message = per_cpu->message;
     74  per_cpu->message = 0;
     75  _SMP_lock_spinlock_simple_Release( &per_cpu->lock, level );
    10476
    10577  #if defined(RTEMS_DEBUG)
     
    10779      void *sp = __builtin_frame_address(0);
    10880      if ( !(message & RTEMS_BSP_SMP_SHUTDOWN) ) {
    109         printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", cpu, message, sp );
     81        printk( "ISR on CPU %d -- (0x%02x) (0x%p)\n", self, message, sp );
    11082        if ( message & RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY )
    11183          printk( "context switch necessary\n" );
     
    11486        if ( message & RTEMS_BSP_SMP_SHUTDOWN )
    11587          printk( "shutdown\n" );
    116         if ( message & RTEMS_BSP_SMP_FIRST_TASK )
    117           printk( "switch to first task\n" );
    11888      }
    11989 
     
    12292  #endif
    12393
    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;
     94  if ( message & RTEMS_BSP_SMP_SHUTDOWN ) {
     95    _ISR_Disable_on_this_core( level );
    12896
    129     _SMP_lock_spinlock_simple_Release( &_Per_CPU_Information[cpu].lock, level );
     97    while ( _Thread_Dispatch_decrement_disable_level() != 0 ) {
     98      /* Release completely */
     99    }
    130100
    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 );
     101    _Per_CPU_Change_state( per_cpu, PER_CPU_STATE_SHUTDOWN );
    144102    while(1)
    145103      ;
    146104    /* does not continue past here */
    147105  }
    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   }
    156106}
    157107
    158 /*
    159  *  Send an interrupt processor request to another cpu.
    160  */
    161 void _SMP_Send_message(
    162   int       cpu,
    163   uint32_t  message
    164 )
     108void _SMP_Send_message( int cpu, uint32_t message )
    165109{
     110  Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
    166111  ISR_Level level;
    167112
     
    171116  #endif
    172117
    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 );
     118  level = _SMP_lock_spinlock_simple_Obtain( &per_cpu->lock );
     119  per_cpu->message |= message;
     120  _SMP_lock_spinlock_simple_Release( &per_cpu->lock, level );
     121
    176122  bsp_smp_interrupt_cpu( cpu );
    177123}
    178124
    179 void _SMP_Broadcast_message(
    180   uint32_t  message
    181 )
     125void _SMP_Broadcast_message( uint32_t message )
    182126{
    183   int        dest_cpu;
    184   int        cpu;
    185   ISR_Level  level;
     127  int self = bsp_smp_processor_id();
     128  int ncpus = _SMP_Processor_count;
     129  int cpu;
    186130
    187   cpu = bsp_smp_processor_id();
     131  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     132    if ( cpu != self ) {
     133      Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
     134      ISR_Level level = _SMP_lock_spinlock_simple_Obtain( &per_cpu->lock );
     135      per_cpu->message |= message;
     136      _SMP_lock_spinlock_simple_Release( &per_cpu->lock, level );
     137    }
     138  }
    188139
    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   }
    196140  bsp_smp_broadcast_interrupt();
    197141}
    198142
    199 void _SMP_Request_other_cores_to_perform_first_context_switch(void)
     143void _SMP_Request_other_cores_to_perform_first_context_switch( void )
    200144{
    201   int    cpu;
     145  int self = bsp_smp_processor_id();
     146  int ncpus = _SMP_Processor_count;
     147  int cpu;
    202148
    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 );
     149  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     150    if ( cpu != self ) {
     151      _Per_CPU_Change_state(
     152        &_Per_CPU_Information[ cpu ],
     153        PER_CPU_STATE_BEGIN_MULTITASKING
     154      );
     155    }
    206156  }
    207157}
    208158
    209 void _SMP_Request_other_cores_to_dispatch(void)
     159void _SMP_Request_other_cores_to_dispatch( void )
    210160{
    211   int i;
    212   int cpu;
     161  if ( _System_state_Is_up( _System_state_Get() ) ) {
     162    int self = bsp_smp_processor_id();
     163    int ncpus = _SMP_Processor_count;
     164    int cpu;
    213165
    214   cpu = bsp_smp_processor_id();
     166    for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     167      const Per_CPU_Control *per_cpu = &_Per_CPU_Information[ cpu ];
    215168
    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 );
     169      if (
     170        cpu != self
     171          && per_cpu->state == PER_CPU_STATE_UP
     172          && per_cpu->dispatch_necessary
     173      ) {
     174        _SMP_Send_message( cpu, RTEMS_BSP_SMP_CONTEXT_SWITCH_NECESSARY );
     175      }
     176    }
    226177  }
    227178}
    228179
    229 void _SMP_Request_other_cores_to_shutdown(void)
     180void _SMP_Request_other_cores_to_shutdown( void )
    230181{
    231   bool   allDown;
    232   int    ncpus;
    233   int    n;
    234   int    cpu;
    235 
    236   cpu   = bsp_smp_processor_id();
    237   ncpus = _SMP_Processor_count;
     182  int self = bsp_smp_processor_id();
     183  int ncpus = _SMP_Processor_count;
     184  int cpu;
    238185
    239186  _SMP_Broadcast_message( RTEMS_BSP_SMP_SHUTDOWN );
    240187
    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;
     188  for ( cpu = 0 ; cpu < ncpus ; ++cpu ) {
     189    if ( cpu != self ) {
     190      _Per_CPU_Wait_for_state(
     191        &_Per_CPU_Information[ cpu ],
     192        PER_CPU_STATE_SHUTDOWN
     193      );
     194    }
    252195  }
    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
    259196}
Note: See TracChangeset for help on using the changeset viewer.