Changeset b8a5abf in rtems


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

score: Update _Thread_Heir only if necessary

Previously, the _Thread_Heir was updated unconditionally in case a new
heir was determined. The _Thread_Dispatch_necessary was only updated in
case the executing thread was preemptible or an internal thread was
unblocked. Change this to update the _Thread_Heir and
_Thread_Dispatch_necessary only in case the currently selected heir
thread is preemptible or a dispatch is forced. Move the schedule
decision into the change priority operation and use the schedule
operation only in rtems_task_mode() in case preemption is enabled or an
ASR dispatch is necessary. This is a behaviour change. Previously, the
RTEMS_NO_PREEMPT also prevented signal delivery in certain cases (not
always). Now, signal delivery is no longer influenced by
RTEMS_NO_PREEMPT. Since the currently selected heir thread is used to
determine if a new heir is chosen, non-preemptible heir threads
currently not executing now prevent a new heir. This may have an
application impact, see change test tm04. Document this change in sp04.

Update #2273.

Files:
14 edited

Legend:

Unmodified
Added
Removed
  • cpukit/rtems/src/taskmode.c

    r81b03c6 rb8a5abf  
    2222#include <rtems/rtems/asrimpl.h>
    2323#include <rtems/rtems/modesimpl.h>
     24#include <rtems/score/schedulerimpl.h>
    2425#include <rtems/score/threadimpl.h>
    2526#include <rtems/config.h>
    26 
    27 static void _RTEMS_Tasks_Dispatch_if_necessary(
    28   Thread_Control *executing,
    29   bool            needs_asr_dispatching
    30 )
    31 {
    32   if ( _Thread_Dispatch_is_enabled() ) {
    33     bool dispatch_necessary = needs_asr_dispatching;
    34 
    35     /*
    36      * FIXME: This locking approach is brittle.  It only works since the
    37      * current simple SMP scheduler has no support for the non-preempt mode.
    38      */
    39 #if defined( RTEMS_SMP )
    40     ISR_Level level;
    41 
    42     _ISR_Disable_without_giant( level );
    43 #endif
    44 
    45     if ( !_Thread_Is_heir( executing ) && executing->is_preemptible ) {
    46       dispatch_necessary = true;
    47       _Thread_Dispatch_necessary = dispatch_necessary;
    48     }
    49 
    50 #if defined( RTEMS_SMP )
    51     _ISR_Enable_without_giant( level );
    52 #endif
    53 
    54     if ( dispatch_necessary ) {
    55       _Thread_Dispatch();
    56     }
    57   }
    58 }
    5927
    6028rtems_status_code rtems_task_mode(
     
    6735  RTEMS_API_Control  *api;
    6836  ASR_Information    *asr;
     37  bool                preempt_enabled;
    6938  bool                needs_asr_dispatching;
    7039  rtems_mode          old_mode;
     
    9261   *  These are generic thread scheduling characteristics.
    9362   */
     63  preempt_enabled = false;
    9464  if ( mask & RTEMS_PREEMPT_MASK ) {
    9565#if defined( RTEMS_SMP )
     
    9969    }
    10070#endif
     71    bool is_preempt_enabled = _Modes_Is_preempt( mode_set );
    10172
    102     executing->is_preemptible = _Modes_Is_preempt( mode_set );
     73    preempt_enabled = !executing->is_preemptible && is_preempt_enabled;
     74    executing->is_preemptible = is_preempt_enabled;
    10375  }
    10476
     
    138110  }
    139111
    140   _RTEMS_Tasks_Dispatch_if_necessary( executing, needs_asr_dispatching );
     112  if ( preempt_enabled || needs_asr_dispatching ) {
     113    ISR_Level level;
     114
     115    _Thread_Disable_dispatch();
     116    _ISR_Disable( level );
     117    _Scheduler_Schedule( executing );
     118    _ISR_Enable( level );
     119    _Thread_Enable_dispatch();
     120  }
    141121
    142122  return RTEMS_SUCCESSFUL;
  • cpukit/score/include/rtems/score/schedulerimpl.h

    r81b03c6 rb8a5abf  
    314314 * must ensure that the priority value actually changed and is not equal to the
    315315 * current priority value.
     316 *
     317 * The operation must update the heir and thread dispatch necessary variables
     318 * in case the set of scheduled threads changes.
    316319 *
    317320 * @param[in] the_thread The thread changing its priority.
     
    631634
    632635RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir(
    633   Thread_Control *heir,
    634   bool force_dispatch
    635 )
    636 {
    637   Thread_Control *executing = _Thread_Executing;
    638 
    639   _Thread_Heir = heir;
    640 
    641   if ( executing != heir && ( force_dispatch || executing->is_preemptible ) )
     636  Thread_Control *new_heir,
     637  bool            force_dispatch
     638)
     639{
     640  Thread_Control *heir = _Thread_Heir;
     641
     642  if ( heir != new_heir && ( heir->is_preemptible || force_dispatch ) ) {
     643    _Thread_Heir = new_heir;
    642644    _Thread_Dispatch_necessary = true;
     645  }
    643646}
    644647
  • cpukit/score/src/schedulercbsunblock.c

    r81b03c6 rb8a5abf  
    8080    )
    8181  ) {
    82     _Thread_Heir = the_thread;
    83     if ( _Thread_Executing->is_preemptible ||
    84          the_thread->current_priority == 0 )
    85       _Thread_Dispatch_necessary = true;
     82    _Scheduler_Update_heir(
     83      the_thread,
     84      the_thread->current_priority == PRIORITY_PSEUDO_ISR
     85    );
    8686  }
    8787
  • cpukit/score/src/scheduleredfchangepriority.c

    r81b03c6 rb8a5abf  
    4040  );
    4141
     42  _Scheduler_EDF_Schedule_body( scheduler, the_thread, false );
     43
    4244  SCHEDULER_RETURN_VOID_OR_NULL;
    4345}
  • cpukit/score/src/scheduleredfunblock.c

    r81b03c6 rb8a5abf  
    4747         _Thread_Heir->current_priority,
    4848         the_thread->current_priority )) {
    49     _Thread_Heir = the_thread;
    50     if ( _Thread_Executing->is_preemptible ||
    51          the_thread->current_priority == 0 )
    52       _Thread_Dispatch_necessary = true;
     49    _Scheduler_Update_heir(
     50      the_thread,
     51      the_thread->current_priority == PRIORITY_PSEUDO_ISR
     52    );
    5353  }
    5454
  • cpukit/score/src/schedulerprioritychangepriority.c

    r81b03c6 rb8a5abf  
    6060  }
    6161
     62  _Scheduler_priority_Schedule_body( scheduler, the_thread, false );
     63
    6264  SCHEDULER_RETURN_VOID_OR_NULL;
    6365}
  • cpukit/score/src/schedulerpriorityunblock.c

    r81b03c6 rb8a5abf  
    5353   */
    5454  if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
    55     _Thread_Heir = the_thread;
    56     if ( _Thread_Executing->is_preemptible ||
    57         the_thread->current_priority == 0 )
    58       _Thread_Dispatch_necessary = true;
     55    _Scheduler_Update_heir(
     56      the_thread,
     57      the_thread->current_priority == PRIORITY_PSEUDO_ISR
     58    );
    5959  }
    6060
  • cpukit/score/src/schedulerpriorityyield.c

    r81b03c6 rb8a5abf  
    3030  Chain_Control *ready_chain = node->Ready_queue.ready_chain;
    3131
    32   (void) scheduler;
    33 
    3432  if ( !_Chain_Has_only_one_node( ready_chain ) ) {
    3533    _Chain_Extract_unprotected( &the_thread->Object.Node );
    3634    _Chain_Append_unprotected( ready_chain, &the_thread->Object.Node );
     35  }
    3736
    38     if ( _Thread_Is_heir( the_thread ) ) {
    39       _Thread_Heir = (Thread_Control *) _Chain_First( ready_chain );
    40     }
    41 
    42     _Thread_Dispatch_necessary = true;
    43   } else if ( !_Thread_Is_heir( the_thread ) ) {
    44     _Thread_Dispatch_necessary = true;
    45   }
     37  _Scheduler_priority_Schedule_body( scheduler, the_thread, true );
    4638
    4739  SCHEDULER_RETURN_VOID_OR_NULL;
  • cpukit/score/src/schedulersimplechangepriority.c

    r81b03c6 rb8a5abf  
    4040  }
    4141
     42  _Scheduler_simple_Schedule_body( scheduler, the_thread, false );
     43
    4244  SCHEDULER_RETURN_VOID_OR_NULL;
    4345}
  • cpukit/score/src/schedulersimpleunblock.c

    r81b03c6 rb8a5abf  
    4545   */
    4646  if ( the_thread->current_priority < _Thread_Heir->current_priority ) {
    47     _Thread_Heir = the_thread;
    48     if ( _Thread_Executing->is_preemptible ||
    49         the_thread->current_priority == 0 )
    50       _Thread_Dispatch_necessary = true;
     47    _Scheduler_Update_heir(
     48      the_thread,
     49      the_thread->current_priority == PRIORITY_PSEUDO_ISR
     50    );
    5151  }
    5252
  • cpukit/score/src/threadchangepriority.c

    r81b03c6 rb8a5abf  
    4747        prepend_it
    4848      );
    49 
    50       _ISR_Flash( level );
    51 
    52       /*
    53        *  We altered the set of thread priorities.  So let's figure out
    54        *  who is the heir and if we need to switch to them.
    55        */
    56       _Scheduler_Schedule( the_thread );
    5749    } else {
    5850      _Scheduler_Update_priority( the_thread, new_priority );
    5951    }
     52
    6053    _ISR_Enable( level );
    6154
  • testsuites/sptests/sp04/system.h

    r81b03c6 rb8a5abf  
    5151#define CONFIGURE_EXTRA_TASK_STACKS         (3 * RTEMS_MINIMUM_STACK_SIZE)
    5252#define CONFIGURE_MAXIMUM_TASKS             4
     53#define CONFIGURE_MAXIMUM_TIMERS            1
    5354
    5455#include <rtems/confdefs.h>
  • testsuites/sptests/sp04/task1.c

    r81b03c6 rb8a5abf  
    3333      print_time( "- ", &taskSwitchLog[i].when, "\n" );
    3434  }
     35}
     36
     37static int test_no_preempt_step;
     38
     39static rtems_id high_task_id;
     40
     41static rtems_id low_task_id;
     42
     43static void high_task( rtems_task_argument arg )
     44{
     45  rtems_status_code sc;
     46
     47  rtems_test_assert( test_no_preempt_step == 2 );
     48  test_no_preempt_step = 3;
     49
     50  sc = rtems_event_transient_send( Task_id[ 1 ] );
     51  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     52
     53  rtems_task_suspend(RTEMS_SELF);
     54  rtems_test_assert(0);
     55}
     56
     57static void low_task( rtems_task_argument arg )
     58{
     59  rtems_test_assert( test_no_preempt_step == 1 );
     60  test_no_preempt_step = 2;
     61
     62  rtems_task_suspend(RTEMS_SELF);
     63  rtems_test_assert(0);
     64}
     65
     66static void no_preempt_timer( rtems_id id, void *arg )
     67{
     68  rtems_status_code sc;
     69
     70  rtems_test_assert( test_no_preempt_step == 0 );
     71  test_no_preempt_step = 1;
     72
     73  sc = rtems_task_start( low_task_id, low_task, 0 );
     74  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     75
     76  sc = rtems_task_start( high_task_id, high_task, 0 );
     77  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     78}
     79
     80static void test_no_preempt( void )
     81{
     82  rtems_status_code sc;
     83  rtems_id id;
     84
     85  rtems_test_assert( test_no_preempt_step == 0 );
     86
     87  sc = rtems_task_delete( Task_id[ 2 ] );
     88  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     89
     90  sc = rtems_task_delete( Task_id[ 3 ] );
     91  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     92
     93  sc = rtems_task_create(
     94    rtems_build_name( 'H', 'I', 'G', 'H' ),
     95    1,
     96    RTEMS_MINIMUM_STACK_SIZE,
     97    RTEMS_DEFAULT_MODES,
     98    RTEMS_DEFAULT_ATTRIBUTES,
     99    &high_task_id
     100  );
     101  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     102
     103  sc = rtems_task_create(
     104    rtems_build_name( 'L', 'O', 'W', ' ' ),
     105    2,
     106    RTEMS_MINIMUM_STACK_SIZE,
     107    RTEMS_NO_PREEMPT,
     108    RTEMS_DEFAULT_ATTRIBUTES,
     109    &low_task_id
     110  );
     111  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     112
     113  sc = rtems_timer_create( rtems_build_name( 'N', 'O', 'P', 'R' ), &id );
     114  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     115
     116  sc = rtems_timer_fire_after( id, 1, no_preempt_timer, NULL );
     117  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     118
     119  sc = rtems_event_transient_receive( RTEMS_WAIT, RTEMS_NO_TIMEOUT );
     120  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     121
     122  sc = rtems_timer_delete( id );
     123  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     124
     125  sc = rtems_task_delete( high_task_id );
     126  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     127
     128  sc = rtems_task_delete( low_task_id );
     129  rtems_test_assert( sc == RTEMS_SUCCESSFUL );
     130
     131  rtems_test_assert( test_no_preempt_step == 3 );
    35132}
    36133
     
    118215      directive_failed( status, "rtems_extension_delete" );
    119216
     217      test_no_preempt();
     218
    120219      TEST_END();
    121220      rtems_test_exit (0);
  • testsuites/tmtests/tm04/task1.c

    r81b03c6 rb8a5abf  
    344344  rtems_id          id;
    345345  rtems_status_code status;
     346  rtems_mode        prev;
    346347
    347348  task_count--;
     
    380381    RTEMS_NO_TIMEOUT
    381382  );
     383
     384  rtems_task_mode(RTEMS_PREEMPT, RTEMS_PREEMPT_MASK, &prev);
    382385}
    383386
Note: See TracChangeset for help on using the changeset viewer.