Changeset 222dc77 in rtems


Ignore:
Timestamp:
Feb 26, 2015, 9:32:08 AM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
1512761
Parents:
6157743
git-author:
Sebastian Huber <sebastian.huber@…> (02/26/15 09:32:08)
git-committer:
Sebastian Huber <sebastian.huber@…> (03/05/15 10:36:19)
Message:

score: Add and use _Thread_Do_dispatch()

The _Thread_Dispatch() function is quite complex and the time to set up
and tear down the stack frame is significant. Split this function into
two parts. The complex part is now in _Thread_Do_dispatch(). Call
_Thread_Do_dispatch() in _Thread_Enable_dispatch() only if necessary.
This increases the average case performance.

Simplify _Thread_Handler() for SMP configurations.

Update #2273.

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/include/rtems/score/threaddispatch.h

    r6157743 r222dc77  
    194194
    195195/**
    196  *  @brief Dispatch thread.
    197  *
    198  *  This routine is responsible for transferring control of the
    199  *  processor from the executing thread to the heir thread. Once the
    200  *  heir is running an attempt is made to dispatch any ASRs.
    201  *  As part of this process, it is responsible for the following actions:
    202  *     + saving the context of the executing thread
    203  *     + restoring the context of the heir thread
    204  *     + dispatching any signals for the resulting executing thread
    205 
    206  *  ALTERNATE ENTRY POINTS:
    207  *    void _Thread_Enable_dispatch();
    208  *
    209  *  - INTERRUPT LATENCY:
    210  *    + dispatch thread
    211  *    + no dispatch thread
     196 * @brief Performs a thread dispatch if necessary.
     197 *
     198 * This routine is responsible for transferring control of the processor from
     199 * the executing thread to the heir thread.  Once the heir is running an
     200 * attempt is made to run the pending post-switch thread actions.
     201 *
     202 * As part of this process, it is responsible for the following actions
     203 *   - update timing information of the executing thread,
     204 *   - save the context of the executing thread,
     205 *   - invokation of the thread switch user extensions,
     206 *   - restore the context of the heir thread, and
     207 *   - run of pending post-switch thread actions of the resulting executing
     208 *     thread.
     209 *
     210 * On entry the thread dispatch level must be equal to zero.
    212211 */
    213212void _Thread_Dispatch( void );
     213
     214/**
     215 * @brief Performs a thread dispatch on the current processor.
     216 *
     217 * On entry the thread dispatch disable level must be equal to one and
     218 * interrupts must be disabled.
     219 *
     220 * This function assumes that a thread dispatch is necessary.
     221 *
     222 * @param[in] cpu_self The current processor.
     223 * @param[in] level The previous interrupt level.
     224 *
     225 * @see _Thread_Dispatch().
     226 */
     227void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level );
    214228
    215229/**
     
    229243RTEMS_INLINE_ROUTINE void _Thread_Enable_dispatch_body( void )
    230244{
    231   if ( _Thread_Dispatch_decrement_disable_level() == 0 )
    232     _Thread_Dispatch();
     245  Per_CPU_Control *cpu_self;
     246  uint32_t         disable_level;
     247
     248  cpu_self = _Per_CPU_Get();
     249
     250#if defined( RTEMS_SMP )
     251  _Giant_Release( cpu_self );
     252#endif
     253
     254  disable_level = cpu_self->thread_dispatch_disable_level;
     255
     256  if ( disable_level == 1 ) {
     257    ISR_Level level;
     258
     259    _ISR_Disable_without_giant( level );
     260
     261    if ( cpu_self->dispatch_necessary ) {
     262      _Thread_Do_dispatch( cpu_self, level );
     263    } else {
     264      cpu_self->thread_dispatch_disable_level = 0;
     265      _Profiling_Thread_dispatch_enable( cpu_self, 0 );
     266    }
     267
     268    _ISR_Enable_without_giant( level );
     269  } else {
     270    cpu_self->thread_dispatch_disable_level = disable_level - 1;
     271  }
    233272}
    234273
  • cpukit/score/src/threaddispatch.c

    r6157743 r222dc77  
    6161}
    6262
    63 void _Thread_Dispatch( void )
     63void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level )
    6464{
    65   Per_CPU_Control  *cpu_self;
    66   Thread_Control   *executing;
    67   ISR_Level         level;
     65  Thread_Control *executing;
    6866
    69 #if defined( RTEMS_SMP )
    70   /*
    71    * On SMP the complete context switch must be atomic with respect to one
    72    * processor.  See also _Thread_Handler() since _Context_switch() may branch
    73    * to this function.
    74    */
    75   _ISR_Disable_without_giant( level );
    76 #endif
     67  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
    7768
    78   cpu_self = _Per_CPU_Get();
    79   _Assert( cpu_self->thread_dispatch_disable_level == 0 );
    80   _Profiling_Thread_dispatch_disable( cpu_self, 0 );
    81   cpu_self->thread_dispatch_disable_level = 1;
    82 
    83   /*
    84    *  Now determine if we need to perform a dispatch on the current CPU.
    85    */
    8669  executing = cpu_self->executing;
    8770
    88 #if !defined( RTEMS_SMP )
    89   _ISR_Disable( level );
    90 #endif
    91 
    92 #if defined( RTEMS_SMP )
    93   if ( cpu_self->dispatch_necessary ) {
    94 #else
    95   while ( cpu_self->dispatch_necessary ) {
    96 #endif
     71  do {
    9772    Thread_Control *heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
    9873
     
    11691      heir->cpu_time_budget = rtems_configuration_get_ticks_per_timeslice();
    11792
     93    /*
     94     * On SMP the complete context switch must be atomic with respect to one
     95     * processor.  See also _Thread_Handler() since _Context_switch() may branch
     96     * to this function.
     97     */
    11898#if !defined( RTEMS_SMP )
    11999    _ISR_Enable( level );
     
    159139    _ISR_Disable( level );
    160140#endif
    161   }
     141  } while (
     142#if defined( RTEMS_SMP )
     143    false
     144#else
     145    cpu_self->dispatch_necessary
     146#endif
     147  );
    162148
    163149post_switch:
     
    170156  _Thread_Run_post_switch_actions( executing );
    171157}
     158
     159void _Thread_Dispatch( void )
     160{
     161  ISR_Level        level;
     162  Per_CPU_Control *cpu_self;
     163
     164  _ISR_Disable_without_giant( level );
     165
     166  cpu_self = _Per_CPU_Get();
     167
     168  if ( cpu_self->dispatch_necessary ) {
     169    _Profiling_Thread_dispatch_disable( cpu_self, 0 );
     170    cpu_self->thread_dispatch_disable_level = 1;
     171    _Thread_Do_dispatch( cpu_self, level );
     172  } else {
     173    _ISR_Enable_without_giant( level );
     174  }
     175}
  • cpukit/score/src/threadhandler.c

    r6157743 r222dc77  
    2727void _Thread_Handler( void )
    2828{
    29   Thread_Control *executing = _Thread_Executing;
    30   ISR_Level       level;
    31 
     29  Thread_Control  *executing = _Thread_Executing;
     30  ISR_Level        level;
     31  Per_CPU_Control *cpu_self;
    3232
    3333  /*
     
    3838  _Context_Initialization_at_thread_begin();
    3939
    40   #if !defined(RTEMS_SMP)
    41     /*
    42      * have to put level into a register for those cpu's that use
    43      * inline asm here
    44      */
    45     level = executing->Start.isr_level;
    46     _ISR_Set_level( level );
     40  #if defined(RTEMS_SMP)
     41    /* On SMP we enter _Thread_Handler() with interrupts disabled */
     42    _Assert( _ISR_Get_level() != 0 );
     43
     44    _Thread_Debug_set_real_processor( executing, _Per_CPU_Get() );
    4745  #endif
     46
     47  /*
     48   * have to put level into a register for those cpu's that use
     49   * inline asm here
     50   */
     51  level = executing->Start.isr_level;
     52  _ISR_Set_level( level );
    4853
    4954  /*
     
    6267
    6368  /*
     69   * Do not use the level of the thread control block, since it has a
     70   * different format.
     71   */
     72  _ISR_Disable_without_giant( level );
     73
     74  /*
    6475   *  At this point, the dispatch disable level BETTER be 1.
    6576   */
    66   #if defined(RTEMS_SMP)
    67     {
    68       /*
    69        * On SMP we enter _Thread_Handler() with interrupts disabled and
    70        * _Thread_Dispatch() obtained the per-CPU lock for us.  We have to
    71        * release it here and set the desired interrupt level of the thread.
    72        */
    73       Per_CPU_Control *cpu_self = _Per_CPU_Get();
     77  cpu_self = _Per_CPU_Get();
     78  _Assert( cpu_self->thread_dispatch_disable_level == 1 );
    7479
    75       _Assert( cpu_self->thread_dispatch_disable_level == 1 );
    76       _Assert( _ISR_Get_level() != 0 );
    77 
    78       _Thread_Debug_set_real_processor( executing, cpu_self );
    79 
    80       cpu_self->thread_dispatch_disable_level = 0;
    81       _Profiling_Thread_dispatch_enable( cpu_self, 0 );
    82 
    83       level = executing->Start.isr_level;
    84       _ISR_Set_level( level);
    85 
    86       /*
    87        * The thread dispatch level changed from one to zero.  Make sure we lose
    88        * no thread dispatch necessary update.
    89        */
    90       _Thread_Dispatch();
    91     }
    92   #else
    93     _Thread_Enable_dispatch();
    94   #endif
     80  /*
     81   * Make sure we lose no thread dispatch necessary update and execute the
     82   * post-switch actions.  As a side-effect change the thread dispatch level
     83   * from one to zero.  Do not use _Thread_Enable_dispatch() since there is no
     84   * valid thread dispatch necessary indicator in this context.
     85   */
     86  _Thread_Do_dispatch( cpu_self, level );
    9587
    9688  /*
  • testsuites/tmtests/tm26/task1.c

    r6157743 r222dc77  
    100100  _Thread_Dispatch_necessary = dispatch_necessary;
    101101
     102  if ( !dispatch_necessary ) {
     103    _Thread_Heir = _Thread_Executing;
     104  }
     105
    102106#if defined( PREVENT_SMP_ASSERT_FAILURES )
    103107  _ISR_Enable_without_giant( level );
Note: See TracChangeset for help on using the changeset viewer.