Ignore:
Timestamp:
May 26, 2014, 2:02:58 PM (7 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
1ee0d5f
Parents:
3045738
git-author:
Sebastian Huber <sebastian.huber@…> (05/26/14 14:02:58)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/03/14 06:15:16)
Message:

score: Use Resource Handler for MrsP semaphores

This enables proper resource dependency tracking and as a side-effect
deadlock detection.

File:
1 edited

Legend:

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

    r3045738 r9553e7a6  
    2222#include <rtems/score/assert.h>
    2323#include <rtems/score/chainimpl.h>
     24#include <rtems/score/resourceimpl.h>
    2425#include <rtems/score/schedulerimpl.h>
    2526#include <rtems/score/watchdogimpl.h>
     
    4243#define MRSP_RIVAL_STATE_TIMEOUT 0x2U
    4344
     45RTEMS_INLINE_ROUTINE bool _MRSP_Set_root_visitor(
     46  Resource_Node *node,
     47  void *arg
     48)
     49{
     50  _Resource_Node_set_root( node, arg );
     51
     52  return false;
     53}
     54
     55RTEMS_INLINE_ROUTINE void _MRSP_Set_root(
     56  Resource_Node *top,
     57  Resource_Node *root
     58)
     59{
     60  _Resource_Node_set_root( top, root );
     61  _Resource_Iterate( top, _MRSP_Set_root_visitor, root );
     62}
     63
     64RTEMS_INLINE_ROUTINE void _MRSP_Elevate_priority(
     65  MRSP_Control     *mrsp,
     66  Thread_Control   *new_owner,
     67  Priority_Control  ceiling_priority
     68)
     69{
     70  _Thread_Change_priority( new_owner, ceiling_priority, false );
     71}
     72
     73RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority(
     74  const MRSP_Control *mrsp,
     75  Thread_Control     *thread,
     76  Priority_Control    initial_priority
     77)
     78{
     79  /*
     80   * The Thread_Control::resource_count is used by the normal priority ceiling
     81   * or priority inheritance semaphores.
     82   */
     83  if ( thread->resource_count == 0 ) {
     84    Priority_Control new_priority = _Scheduler_Highest_priority_of_two(
     85      _Scheduler_Get( thread ),
     86      initial_priority,
     87      thread->real_priority
     88    );
     89
     90    _Thread_Change_priority( thread, new_priority, true );
     91  }
     92}
     93
    4494RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
    4595  MRSP_Control     *mrsp,
    4696  Thread_Control   *new_owner,
     97  Priority_Control  initial_priority,
    4798  Priority_Control  ceiling_priority
    4899)
    49100{
    50   ++new_owner->resource_count;
    51   mrsp->owner = new_owner;
    52   _Thread_Change_priority( new_owner, ceiling_priority, false );
     101  _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
     102  _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
     103  mrsp->initial_priority_of_owner = initial_priority;
     104  _MRSP_Elevate_priority( mrsp, new_owner, ceiling_priority );
    53105}
    54106
     
    78130  }
    79131
    80   mrsp->owner = NULL;
     132  _Resource_Initialize( &mrsp->Resource );
    81133  _Chain_Initialize_empty( &mrsp->Rivals );
    82134
     
    101153}
    102154
    103 RTEMS_INLINE_ROUTINE void _MRSP_Restore_priority( Thread_Control *thread )
    104 {
    105   _Thread_Change_priority( thread, thread->real_priority, true );
    106 }
    107 
    108155RTEMS_INLINE_ROUTINE void _MRSP_Add_state(
    109156  MRSP_Rival   *rival,
     
    128175RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
    129176  MRSP_Control      *mrsp,
     177  Resource_Node     *owner,
    130178  Thread_Control    *executing,
     179  Priority_Control   initial_priority,
    131180  Priority_Control   ceiling_priority,
    132181  Watchdog_Interval  timeout
     
    138187  unsigned int state;
    139188
    140   _Thread_Change_priority( executing, ceiling_priority, false );
     189  _MRSP_Elevate_priority( mrsp, executing, ceiling_priority );
    141190
    142191  rival.thread = executing;
    143192  _Atomic_Init_uint( &rival.state, MRSP_RIVAL_STATE_WAITING );
    144193  _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node );
     194  _Resource_Add_rival( &mrsp->Resource, &executing->Resource_node );
     195  _Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource );
     196  _MRSP_Set_root( &executing->Resource_node, owner );
    145197
    146198  if ( timeout > 0 ) {
     
    177229
    178230  if ( ( state & MRSP_RIVAL_STATE_NEW_OWNER ) != 0 ) {
    179     ++executing->resource_count;
    180 
     231    mrsp->initial_priority_of_owner = initial_priority;
    181232    status = MRSP_SUCCESSFUL;
    182233  } else {
    183     if ( executing->resource_count == 0 ) {
    184       _MRSP_Restore_priority( executing );
    185     }
     234    Resource_Node *executing_node = &executing->Resource_node;
     235
     236    _Resource_Node_extract( executing_node );
     237    _Resource_Node_set_dependency( executing_node, NULL );
     238    _MRSP_Set_root( executing_node, executing_node );
     239    _MRSP_Restore_priority( mrsp, executing, initial_priority );
    186240
    187241    status = MRSP_TIMEOUT;
     
    201255  const Scheduler_Control *scheduler = _Scheduler_Get( executing );
    202256  uint32_t scheduler_index = _Scheduler_Get_index( scheduler );
     257  Priority_Control initial_priority = executing->current_priority;
    203258  Priority_Control ceiling_priority =
    204259    _MRSP_Get_ceiling_priority( mrsp, scheduler_index );
    205260  bool priority_ok = !_Scheduler_Is_priority_higher_than(
    206261    scheduler,
    207     executing->current_priority,
     262    initial_priority,
    208263    ceiling_priority
    209264  );
     265  Resource_Node *owner;
    210266
    211267  if ( !priority_ok) {
     
    213269  }
    214270
    215   if ( mrsp->owner == NULL ) {
    216     _MRSP_Claim_ownership( mrsp, executing, ceiling_priority );
     271  owner = _Resource_Get_owner( &mrsp->Resource );
     272  if ( owner == NULL ) {
     273    _MRSP_Claim_ownership(
     274      mrsp,
     275      executing,
     276      initial_priority,
     277      ceiling_priority
     278    );
    217279    status = MRSP_SUCCESSFUL;
    218   } else if ( mrsp->owner == executing ) {
     280  } else if ( _Resource_Node_get_root( owner ) == &executing->Resource_node ) {
     281    /* Nested access or deadlock */
    219282    status = MRSP_UNSATISFIED;
    220283  } else if ( wait ) {
    221284    status = _MRSP_Wait_for_ownership(
    222285      mrsp,
     286      owner,
    223287      executing,
     288      initial_priority,
    224289      ceiling_priority,
    225290      timeout
     
    237302)
    238303{
    239   uint32_t resource_count = executing->resource_count;
    240 
    241   if ( mrsp->owner != executing ) {
     304  if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) {
    242305    return MRSP_NOT_OWNER_OF_RESOURCE;
    243306  }
    244307
    245   if ( resource_count == 1 ) {
    246     executing->resource_count = 0;
    247     _MRSP_Restore_priority( executing );
    248   } else {
    249     executing->resource_count = resource_count - 1;
    250   }
     308  if (
     309    !_Resource_Is_most_recently_obtained(
     310      &mrsp->Resource,
     311      &executing->Resource_node
     312    )
     313  ) {
     314    return MRSP_INCORRECT_STATE;
     315  }
     316
     317  _Resource_Extract( &mrsp->Resource );
     318  _MRSP_Restore_priority( mrsp, executing, mrsp->initial_priority_of_owner );
    251319
    252320  if ( _Chain_Is_empty( &mrsp->Rivals ) ) {
    253     mrsp->owner = NULL;
     321    _Resource_Set_owner( &mrsp->Resource, NULL );
    254322  } else {
    255323    MRSP_Rival *rival = (MRSP_Rival *) _Chain_First( &mrsp->Rivals );
    256 
    257     mrsp->owner = rival->thread;
     324    Resource_Node *new_owner = &rival->thread->Resource_node;
     325
     326    _Resource_Node_extract( new_owner );
     327    _Resource_Node_set_dependency( new_owner, NULL );
     328    _MRSP_Set_root( new_owner, new_owner );
     329    _Resource_Node_add_resource( new_owner, &mrsp->Resource );
     330    _Resource_Set_owner( &mrsp->Resource, new_owner );
    258331    _MRSP_Add_state( rival, MRSP_RIVAL_STATE_NEW_OWNER );
    259332  }
     
    264337RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Destroy( MRSP_Control *mrsp )
    265338{
    266   if ( mrsp->owner != NULL ) {
     339  if ( _Resource_Get_owner( &mrsp->Resource ) != NULL ) {
    267340    return MRSP_RESOUCE_IN_USE;
    268341  }
Note: See TracChangeset for help on using the changeset viewer.