Changeset 3ad5f86 in rtems


Ignore:
Timestamp:
Jun 3, 2016, 6:15:21 AM (3 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
214156d
Parents:
a2f91f6
git-author:
Sebastian Huber <sebastian.huber@…> (06/03/16 06:15:21)
git-committer:
Sebastian Huber <sebastian.huber@…> (06/06/16 10:57:07)
Message:

rtems: Fix no protocol mutex release

The Classic binary semaphores without a locking protocol
(RTEMS_BINARY_SEMAPHORE) could be released by everyone, e.g. in contrast
to the POSIX mutexes (all variants) or the Classic binary semphores with
priority inheritance or ceiling, there was no owner check in the release
path.

This behaviour was a bit unexpected and not documented. Add an owner
check to the release path. Update sptests/sp42 accordingly.

This change has nothing to do with the simple binary semaphores
(RTEMS_SIMPLE_BINARY_SEMAPHORE) which have no owner at all.

Update #2725

Files:
4 edited

Legend:

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

    ra2f91f6 r3ad5f86  
    6565      break;
    6666    case SEMAPHORE_VARIANT_MUTEX_NO_PROTOCOL:
    67       _CORE_recursive_mutex_Surrender_no_protocol_classic(
     67      _CORE_recursive_mutex_Surrender_no_protocol(
    6868        &the_semaphore->Core_control.Mutex.Recursive,
    6969        _Semaphore_Get_operations( the_semaphore ),
     70        executing,
    7071        &queue_context
    7172      );
  • cpukit/score/include/rtems/score/coremuteximpl.h

    ra2f91f6 r3ad5f86  
    312312}
    313313
    314 RTEMS_INLINE_ROUTINE void
    315 _CORE_recursive_mutex_Surrender_no_protocol_finalize(
     314RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender_no_protocol(
    316315  CORE_recursive_mutex_Control  *the_mutex,
    317316  const Thread_queue_Operations *operations,
     317  Thread_Control                *executing,
    318318  Thread_queue_Context          *queue_context
    319319)
     
    322322  Thread_Control *new_owner;
    323323
     324  _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
     325
     326  if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
     327    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
     328    return STATUS_NOT_OWNER;
     329  }
     330
    324331  nest_level = the_mutex->nest_level;
    325332
     
    327334    the_mutex->nest_level = nest_level - 1;
    328335    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
    329     return;
     336    return STATUS_SUCCESSFUL;
    330337  }
    331338
     
    338345  if ( new_owner == NULL ) {
    339346    _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
    340     return;
     347    return STATUS_SUCCESSFUL;
    341348  }
    342349
     
    347354    queue_context
    348355  );
    349 }
    350 
    351 RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender_no_protocol(
    352   CORE_recursive_mutex_Control  *the_mutex,
    353   const Thread_queue_Operations *operations,
    354   Thread_Control                *executing,
    355   Thread_queue_Context          *queue_context
    356 )
    357 {
    358   _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
    359 
    360   if ( !_CORE_mutex_Is_owner( &the_mutex->Mutex, executing ) ) {
    361     _CORE_mutex_Release( &the_mutex->Mutex, queue_context );
    362     return STATUS_NOT_OWNER;
    363   }
    364 
    365   _CORE_recursive_mutex_Surrender_no_protocol_finalize(
    366     the_mutex,
    367     operations,
    368     queue_context
    369   );
    370356  return STATUS_SUCCESSFUL;
    371 }
    372 
    373 /*
    374  * The Classic no protocol recursive mutex has the nice property that everyone
    375  * can release it.
    376  */
    377 RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Surrender_no_protocol_classic(
    378   CORE_recursive_mutex_Control  *the_mutex,
    379   const Thread_queue_Operations *operations,
    380   Thread_queue_Context          *queue_context
    381 )
    382 {
    383   _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context );
    384   _CORE_recursive_mutex_Surrender_no_protocol_finalize(
    385     the_mutex,
    386     operations,
    387     queue_context
    388   );
    389357}
    390358
  • testsuites/sptests/sp42/init.c

    ra2f91f6 r3ad5f86  
    2525#define MAX_TASKS 20
    2626
    27 rtems_task Init(rtems_task_argument argument);
    28 rtems_task Locker_task(rtems_task_argument unused);
    29 void do_test(
    30   rtems_attribute attr,
    31   bool            extract  /* TRUE if extract, not release */
    32 );
    33 
    3427/*
    3528 * Carefully chosen to exercise threadq enqueue/dequeue priority logic.
     
    3730 * behavior won't be the same when released.
    3831 */
    39 rtems_task_priority Priorities_High[MAX_TASKS] = {
     32static const rtems_task_priority Priorities_High[MAX_TASKS] = {
    4033  37, 37, 37, 37,       /* backward - more 2-n */
    4134  2, 2, 2, 2,           /* forward - multiple are on 2-n chain */
     
    4639};
    4740
    48 rtems_task_priority Priorities_Low[MAX_TASKS] = {
     41static const rtems_task_priority Priorities_Low[MAX_TASKS] = {
    4942  13, 13, 13, 13,       /* backward - more 2-n */
    5043  2, 2, 2, 2,           /* forward - multiple are on 2-n chain */
     
    5548};
    5649
    57 rtems_task_priority *Priorities;
    58 
    59 rtems_id   Semaphore;
    60 rtems_id   Task_id[ MAX_TASKS ];
    61 rtems_name Task_name[ MAX_TASKS ];
    62 
    63 rtems_task Locker_task(
    64   rtems_task_argument unused
     50static const int Obtain_order[2][MAX_TASKS] = {
     51  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
     52  { 4, 5, 6, 7, 9, 10, 11, 12, 13, 8, 16, 17, 18, 19, 0, 1, 2, 3, 15, 14 }
     53};
     54
     55static const rtems_task_priority *Priorities;
     56
     57static rtems_id   Semaphore;
     58static rtems_id   Master;
     59static rtems_id   Task_id[ MAX_TASKS ];
     60static rtems_name Task_name[ MAX_TASKS ];
     61
     62static rtems_task_argument Obtain_counter;
     63
     64static enum {
     65 FIFO,
     66 PRIORITY
     67} Variant;
     68
     69static rtems_task Locker_task(
     70  rtems_task_argument task_index
    6571)
    6672{
    67   rtems_id          tid;
    68   uint32_t          task_index;
    69   rtems_status_code status;
     73  rtems_id            tid;
     74  rtems_status_code   status;
     75  rtems_task_argument my_obtain_counter;
    7076
    7177  status = rtems_task_ident( RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &tid );
    7278  directive_failed( status, "rtems_task_ident" );
    7379
    74   task_index = task_number( tid ) - 1;
     80  rtems_test_assert( task_index == task_number( tid ) - 1 );
    7581
    7682  status = rtems_semaphore_obtain( Semaphore, RTEMS_DEFAULT_OPTIONS, 0 );
     
    8086  puts( " - unblocked - OK" );
    8187
     88  status = rtems_task_wake_after( 10 );
     89  directive_failed( status, "rtems_task_wake_after" );
     90
     91  my_obtain_counter = Obtain_counter;
     92  rtems_test_assert( task_index == Obtain_order[ Variant ][ Obtain_counter ] );
     93  ++Obtain_counter;
     94
     95  status = rtems_semaphore_release( Semaphore );
     96  directive_failed( status, "rtems_semaphore_release" );
     97
     98  if ( my_obtain_counter == MAX_TASKS - 1 ) {
     99    status = rtems_event_transient_send( Master );
     100    directive_failed( status, "rtems_event_transient_send" );
     101  }
     102
    82103  (void) rtems_task_delete( RTEMS_SELF );
    83104}
    84105
    85 void do_test(
     106static void do_test(
    86107  rtems_attribute attr,
    87108  bool            extract  /* TRUE if extract, not release */
    88109)
    89110{
    90   rtems_status_code status;
    91   int               i;
     111  rtems_status_code   status;
     112  rtems_task_argument i;
     113
     114  Variant = ( ( attr & RTEMS_PRIORITY ) != 0 ? PRIORITY : FIFO );
     115  Obtain_counter = 0;
    92116
    93117  status = rtems_semaphore_create(
    94118    rtems_build_name( 'S', 'E', 'M', '0' ),  /* name = SEM0 */
    95     0,                                       /* unlocked */
     119    0,                                       /* locked */
    96120    RTEMS_BINARY_SEMAPHORE | attr,           /* mutex w/desired discipline */
    97121    0,                                       /* IGNORED */
     
    100124  directive_failed( status, "rtems_semaphore_create" );
    101125
    102   for (i=0 ; i< MAX_TASKS ; i++ ) {
    103 
     126  for (i = 0 ; i < MAX_TASKS ; i++ ) {
    104127    Task_name[ i ] = rtems_build_name(
    105128       'T',
     
    119142    directive_failed( status, "rtems_task_create" );
    120143
    121     status = rtems_task_start(
    122       Task_id[ i ], Locker_task, (rtems_task_argument)i );
     144    status = rtems_task_start( Task_id[ i ], Locker_task, i );
    123145    directive_failed( status, "rtems_task_start" );
    124 
    125     status = rtems_task_wake_after( 10 );
    126     directive_failed( status, "rtems_task_wake_after" );
    127   }
    128 
    129   for (i=0 ; i< MAX_TASKS ; i++ ) {
    130     if ( extract == FALSE ) {
    131       status = rtems_semaphore_release( Semaphore );
    132       directive_failed( status, "rtems_semaphore_release" );
    133 
    134       status = rtems_task_wake_after( 100 );
    135       directive_failed( status, "rtems_task_wake_after" );
    136     } else {
     146  }
     147
     148  if ( extract ) {
     149    for (i = 0 ; i< MAX_TASKS ; i++ ) {
    137150      status = rtems_task_delete( Task_id[ i ]  );
    138151      directive_failed( status, "rtems_task_delete" );
     
    140153  }
    141154
    142   /* one extra release for the initial state */
     155  /* do the initial release */
    143156  status = rtems_semaphore_release( Semaphore );
    144157  directive_failed( status, "rtems_semaphore_release" );
     158
     159  if ( !extract ) {
     160    status = rtems_event_transient_receive( RTEMS_WAIT, RTEMS_NO_TIMEOUT );
     161    directive_failed( status, "rtems_event_transient_receive" );
     162  }
    145163
    146164  /* now delete the semaphore since no one is waiting and it is unlocked */
     
    149167}
    150168
    151 rtems_task Init(
     169static rtems_task Init(
    152170  rtems_task_argument argument
    153171)
    154172{
     173  rtems_task_priority prio;
     174  rtems_status_code status;
     175
    155176  TEST_BEGIN();
     177
     178  Master = rtems_task_self();
    156179
    157180  if (RTEMS_MAXIMUM_PRIORITY == 255)
     
    164187  }
    165188
     189  prio = RTEMS_MAXIMUM_PRIORITY - 1;
     190  status = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
     191  directive_failed( status, "rtems_task_set_priority" );
     192
    166193  if ( sizeof(Priorities_Low) / sizeof(rtems_task_priority) != MAX_TASKS ) {
    167194    puts( "Priorities_Low table does not have right number of entries" );
     
    202229#define CONFIGURE_MAXIMUM_SEMAPHORES        1
    203230
     231#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
     232
    204233#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
    205234
  • testsuites/sptests/sp42/sp42.scn

    ra2f91f6 r3ad5f86  
    1 *** START OF TEST 42 ***
     1*** BEGIN OF TEST SP 42 ***
    22Exercising blocking discipline w/extract in FIFO order
    33Exercising blocking discipline w/unblock in FIFO order
     
    4545TA15 - unblocked - OK
    4646TA14 - unblocked - OK
    47 *** END OF TEST 42 ***
     47*** END OF TEST SP 42 ***
Note: See TracChangeset for help on using the changeset viewer.