Ignore:
Timestamp:
Dec 17, 2014, 2:11:00 PM (5 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
8ce00eaf
Parents:
481054e0
git-author:
Sebastian Huber <sebastian.huber@…> (12/17/14 14:11:00)
git-committer:
Sebastian Huber <sebastian.huber@…> (12/18/14 07:33:29)
Message:

smp: Fix timeout for MrsP semaphores

The previous timeout handling was flawed. In case a waiting thread
helped out the owner could use the scheduler node indefinitely long.
Update the resource tree in _MRSP_Timeout() to avoid this issue.

Bug reported by Luca Bonato.

File:
1 edited

Legend:

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

    r481054e0 r864d3475  
    3737 */
    3838
    39 #define MRSP_RIVAL_STATE_WAITING 0x0U
    40 
    41 #define MRSP_RIVAL_STATE_NEW_OWNER 0x1U
    42 
    43 #define MRSP_RIVAL_STATE_TIMEOUT 0x2U
    44 
    4539RTEMS_INLINE_ROUTINE void _MRSP_Elevate_priority(
    4640  MRSP_Control     *mrsp,
     
    5347
    5448RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority(
    55   const MRSP_Control *mrsp,
    56   Thread_Control     *thread,
    57   Priority_Control    initial_priority
     49  Thread_Control   *thread,
     50  Priority_Control  initial_priority
    5851)
    5952{
     
    135128}
    136129
    137 RTEMS_INLINE_ROUTINE void _MRSP_Add_state(
    138   MRSP_Rival   *rival,
    139   unsigned int  state
    140 )
    141 {
    142   _Atomic_Fetch_or_uint( &rival->state, state, ATOMIC_ORDER_RELEASE );
    143 }
    144 
    145130RTEMS_INLINE_ROUTINE void _MRSP_Timeout(
    146131  Objects_Id  id,
     
    149134{
    150135  MRSP_Rival *rival = arg;
     136  Thread_Control *thread = rival->thread;
     137  ISR_Level level;
    151138
    152139  (void) id;
    153140
    154   _MRSP_Add_state( rival, MRSP_RIVAL_STATE_TIMEOUT );
     141  _ISR_Disable( level );
     142
     143  if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) {
     144    _Chain_Extract_unprotected( &rival->Node );
     145
     146    _ISR_Enable( level );
     147
     148    rival->status = MRSP_TIMEOUT;
     149
     150    _Resource_Node_extract( &thread->Resource_node );
     151    _Resource_Node_set_dependency( &thread->Resource_node, NULL );
     152    _Scheduler_Thread_change_help_state( thread, rival->initial_help_state );
     153    _Scheduler_Thread_change_resource_root( thread, thread );
     154    _MRSP_Restore_priority( thread, rival->initial_priority );
     155  } else {
     156    _ISR_Enable( level );
     157  }
    155158}
    156159
     
    166169  MRSP_Status status;
    167170  MRSP_Rival rival;
    168   bool previous_life_protection;
    169   unsigned int state;
    170   Scheduler_Help_state previous_help_state;
     171  bool initial_life_protection;
     172  ISR_Level level;
     173
     174  rival.thread = executing;
     175  rival.initial_priority = initial_priority;
     176  rival.initial_help_state =
     177    _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_ACTIVE_RIVAL );
     178  rival.status = MRSP_WAIT_FOR_OWNERSHIP;
    171179
    172180  _MRSP_Elevate_priority( mrsp, executing, ceiling_priority );
    173181
    174   rival.thread = executing;
    175   _Atomic_Init_uint( &rival.state, MRSP_RIVAL_STATE_WAITING );
     182  _ISR_Disable( level );
    176183  _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node );
     184  _ISR_Enable( level );
     185
    177186  _Resource_Add_rival( &mrsp->Resource, &executing->Resource_node );
    178187  _Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource );
    179   previous_help_state =
    180     _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_ACTIVE_RIVAL );
    181188
    182189  _Scheduler_Thread_change_resource_root(
     
    195202  }
    196203
    197   previous_life_protection = _Thread_Set_life_protection( true );
     204  initial_life_protection = _Thread_Set_life_protection( true );
    198205  _Thread_Enable_dispatch();
    199206
    200207  _Assert( _Debug_Is_thread_dispatching_allowed() );
    201208
    202   while (
    203     _Atomic_Load_uint( &rival.state, ATOMIC_ORDER_ACQUIRE )
    204       == MRSP_RIVAL_STATE_WAITING
    205   ) {
    206     /* Wait for state change */
    207   }
     209  /* Wait for state change */
     210  do {
     211    status = rival.status;
     212  } while ( status == MRSP_WAIT_FOR_OWNERSHIP );
    208213
    209214  _Thread_Disable_dispatch();
    210   _Thread_Set_life_protection( previous_life_protection );
     215  _Thread_Set_life_protection( initial_life_protection );
    211216
    212217  if ( timeout > 0 ) {
    213218    _Watchdog_Remove( &executing->Timer );
    214   }
    215 
    216   _Chain_Extract_unprotected( &rival.Node );
    217   state = _Atomic_Load_uint( &rival.state, ATOMIC_ORDER_RELAXED );
    218 
    219   if ( ( state & MRSP_RIVAL_STATE_NEW_OWNER ) != 0 ) {
    220     mrsp->initial_priority_of_owner = initial_priority;
    221     status = MRSP_SUCCESSFUL;
    222   } else {
    223     _Resource_Node_extract( &executing->Resource_node );
    224     _Resource_Node_set_dependency( &executing->Resource_node, NULL );
    225     _Scheduler_Thread_change_help_state( executing, previous_help_state );
    226     _Scheduler_Thread_change_resource_root( executing, executing );
    227     _MRSP_Restore_priority( mrsp, executing, initial_priority );
    228 
    229     status = MRSP_TIMEOUT;
    230219  }
    231220
     
    290279)
    291280{
     281  ISR_Level level;
     282
    292283  if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) {
    293284    return MRSP_NOT_OWNER_OF_RESOURCE;
     
    304295
    305296  _Resource_Extract( &mrsp->Resource );
    306   _MRSP_Restore_priority( mrsp, executing, mrsp->initial_priority_of_owner );
     297  _MRSP_Restore_priority( executing, mrsp->initial_priority_of_owner );
     298
     299  _ISR_Disable( level );
    307300
    308301  if ( _Chain_Is_empty( &mrsp->Rivals ) ) {
     302    _ISR_Enable( level );
     303
    309304    _Resource_Set_owner( &mrsp->Resource, NULL );
    310305  } else {
    311     MRSP_Rival *rival = (MRSP_Rival *) _Chain_First( &mrsp->Rivals );
    312     Thread_Control *new_owner = rival->thread;
    313 
     306    MRSP_Rival *rival = (MRSP_Rival *)
     307      _Chain_Get_first_unprotected( &mrsp->Rivals );
     308    Thread_Control *new_owner;
     309
     310    /*
     311     * This must be inside the critical section since the status prevents a
     312     * potential double extraction in _MRSP_Timeout().
     313     */
     314    rival->status = MRSP_SUCCESSFUL;
     315
     316    _ISR_Enable( level );
     317
     318    new_owner = rival->thread;
     319    mrsp->initial_priority_of_owner = rival->initial_priority;
    314320    _Resource_Node_extract( &new_owner->Resource_node );
    315321    _Resource_Node_set_dependency( &new_owner->Resource_node, NULL );
     
    318324    _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
    319325    _Scheduler_Thread_change_resource_root( new_owner, new_owner );
    320     _MRSP_Add_state( rival, MRSP_RIVAL_STATE_NEW_OWNER );
    321326  }
    322327
Note: See TracChangeset for help on using the changeset viewer.