Changeset f27383a in rtems


Ignore:
Timestamp:
Apr 20, 2016, 12:01:02 PM (4 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
84a53988
Parents:
5c9fa6f
git-author:
Sebastian Huber <sebastian.huber@…> (04/20/16 12:01:02)
git-committer:
Sebastian Huber <sebastian.huber@…> (04/22/16 07:25:09)
Message:

score: Avoid Giant lock for barriers

Use _Thread_queue_Flush_critical() to atomically release the barrier.

Update #2555.

Location:
cpukit
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • cpukit/posix/include/rtems/posix/barrierimpl.h

    r5c9fa6f rf27383a  
    2424#include <rtems/score/objectimpl.h>
    2525
     26#include <errno.h>
    2627#include <pthread.h>
    2728
     
    7778}
    7879
    79 /**
    80  * @brief Get a barrier control block.
    81  *
    82  * This function maps barrier IDs to barrier control blocks.
    83  * If ID corresponds to a local barrier, then it returns
    84  * the_barrier control pointer which maps to ID and location
    85  * is set to OBJECTS_LOCAL.  if the barrier ID is global and
    86  * resides on a remote node, then location is set to OBJECTS_REMOTE,
    87  * and the_barrier is undefined.  Otherwise, location is set
    88  * to OBJECTS_ERROR and the_barrier is undefined.
    89  */
    9080RTEMS_INLINE_ROUTINE POSIX_Barrier_Control *_POSIX_Barrier_Get (
    91   pthread_barrier_t *barrier,
    92   Objects_Locations *location
     81  const pthread_barrier_t *barrier,
     82  ISR_lock_Context        *lock_context
    9383)
    9484{
    95   return (POSIX_Barrier_Control *) _Objects_Get(
    96       &_POSIX_Barrier_Information,
    97       (Objects_Id) *barrier,
    98       location
     85  return (POSIX_Barrier_Control *) _Objects_Get_local(
     86    (Objects_Id) *barrier,
     87    &_POSIX_Barrier_Information,
     88    lock_context
    9989  );
    10090}
  • cpukit/posix/src/pbarrierdestroy.c

    r5c9fa6f rf27383a  
    1919#endif
    2020
    21 #include <pthread.h>
    22 #include <errno.h>
    23 
    24 #include <rtems/system.h>
    2521#include <rtems/posix/barrierimpl.h>
    2622
     
    4036)
    4137{
    42   POSIX_Barrier_Control *the_barrier = NULL;
    43   Objects_Locations      location;
     38  POSIX_Barrier_Control *the_barrier;
     39  ISR_lock_Context       lock_context;
    4440
    45   if ( !barrier )
     41  if ( barrier == NULL ) {
    4642    return EINVAL;
     43  }
    4744
    4845  _Objects_Allocator_lock();
    49   the_barrier = _POSIX_Barrier_Get( barrier, &location );
    50   switch ( location ) {
     46  the_barrier = _POSIX_Barrier_Get( barrier, &lock_context );
    5147
    52     case OBJECTS_LOCAL:
    53       if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) {
    54         _Objects_Put( &the_barrier->Object );
    55         return EBUSY;
    56       }
    57 
    58       _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object );
    59       _Objects_Put( &the_barrier->Object );
    60 
    61       _POSIX_Barrier_Free( the_barrier );
    62       _Objects_Allocator_unlock();
    63       return 0;
    64 
    65 #if defined(RTEMS_MULTIPROCESSING)
    66     case OBJECTS_REMOTE:
    67 #endif
    68     case OBJECTS_ERROR:
    69       break;
     48  if ( the_barrier == NULL ) {
     49    _Objects_Allocator_unlock();
     50    return EINVAL;
    7051  }
    7152
     53  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
     54
     55  if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) {
     56    _CORE_barrier_Release( &the_barrier->Barrier, &lock_context );
     57    _Objects_Allocator_unlock();
     58    return EBUSY;
     59  }
     60
     61  _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object );
     62  _CORE_barrier_Release( &the_barrier->Barrier, &lock_context );
     63  _POSIX_Barrier_Free( the_barrier );
    7264  _Objects_Allocator_unlock();
    73 
    74   return EINVAL;
     65  return 0;
    7566}
  • cpukit/posix/src/pbarrierwait.c

    r5c9fa6f rf27383a  
    1919#endif
    2020
    21 #include <pthread.h>
    22 #include <errno.h>
    23 
    2421#include <rtems/posix/barrierimpl.h>
    2522#include <rtems/score/threadimpl.h>
     
    4138)
    4239{
    43   POSIX_Barrier_Control   *the_barrier = NULL;
    44   Objects_Locations        location;
    45   Thread_Control          *executing;
     40  POSIX_Barrier_Control *the_barrier;
     41  ISR_lock_Context       lock_context;
     42  Thread_Control        *executing;
    4643
    47   if ( !barrier )
     44  if ( barrier == NULL ) {
    4845    return EINVAL;
    49 
    50   the_barrier = _POSIX_Barrier_Get( barrier, &location );
    51   switch ( location ) {
    52 
    53     case OBJECTS_LOCAL:
    54       executing = _Thread_Executing;
    55       _CORE_barrier_Seize(
    56         &the_barrier->Barrier,
    57         executing,
    58         true,
    59         0,
    60         NULL,
    61         0
    62       );
    63       _Objects_Put( &the_barrier->Object );
    64       return _POSIX_Barrier_Translate_core_barrier_return_code(
    65                 executing->Wait.return_code );
    66 
    67 #if defined(RTEMS_MULTIPROCESSING)
    68     case OBJECTS_REMOTE:
    69 #endif
    70     case OBJECTS_ERROR:
    71       break;
    7246  }
    7347
    74   return EINVAL;
     48  the_barrier = _POSIX_Barrier_Get( barrier, &lock_context );
     49
     50  if ( the_barrier == NULL ) {
     51    return EINVAL;
     52  }
     53
     54  executing = _Thread_Executing;
     55  _CORE_barrier_Seize(
     56    &the_barrier->Barrier,
     57    executing,
     58    true,
     59    0,
     60    NULL,
     61    0,
     62    &lock_context
     63  );
     64  return _POSIX_Barrier_Translate_core_barrier_return_code(
     65    executing->Wait.return_code
     66  );
    7567}
  • cpukit/rtems/include/rtems/rtems/barrierimpl.h

    r5c9fa6f rf27383a  
    7070}
    7171
    72 /**
    73  *  @brief _Barrier_Get
    74  *
    75  *  This function maps barrier IDs to barrier control blocks.
    76  *  If ID corresponds to a local barrier, then it returns
    77  *  the_barrier control pointer which maps to ID and location
    78  *  is set to OBJECTS_LOCAL.  if the barrier ID is global and
    79  *  resides on a remote node, then location is set to OBJECTS_REMOTE,
    80  *  and the_barrier is undefined.  Otherwise, location is set
    81  *  to OBJECTS_ERROR and the_barrier is undefined.
    82  */
    83 RTEMS_INLINE_ROUTINE Barrier_Control *_Barrier_Get (
    84   Objects_Id         id,
    85   Objects_Locations *location
     72RTEMS_INLINE_ROUTINE Barrier_Control *_Barrier_Get(
     73  Objects_Id        id,
     74  ISR_lock_Context *lock_context
    8675)
    8776{
    8877  return (Barrier_Control *)
    89     _Objects_Get( &_Barrier_Information, id, location );
     78    _Objects_Get_local( id, &_Barrier_Information, lock_context );
    9079}
    9180
  • cpukit/rtems/src/barrierdelete.c

    r5c9fa6f rf27383a  
    2020
    2121#include <rtems/rtems/barrierimpl.h>
    22 #include <rtems/score/threadqimpl.h>
    2322
    2423rtems_status_code rtems_barrier_delete(
     
    2625)
    2726{
    28   Barrier_Control   *the_barrier;
    29   Objects_Locations  location;
     27  Barrier_Control  *the_barrier;
     28  ISR_lock_Context  lock_context;
    3029
    3130  _Objects_Allocator_lock();
    32   the_barrier = _Barrier_Get( id, &location );
    33   switch ( location ) {
     31  the_barrier = _Barrier_Get( id, &lock_context );
    3432
    35     case OBJECTS_LOCAL:
    36       _Objects_Close( &_Barrier_Information, &the_barrier->Object );
    37       _CORE_barrier_Flush( &the_barrier->Barrier, NULL, 0 );
    38       _Objects_Put( &the_barrier->Object );
    39       _Barrier_Free( the_barrier );
    40       _Objects_Allocator_unlock();
    41       return RTEMS_SUCCESSFUL;
    42 
    43 #if defined(RTEMS_MULTIPROCESSING)
    44     case OBJECTS_REMOTE:
    45 #endif
    46     case OBJECTS_ERROR:
    47       break;
     33  if ( the_barrier == NULL ) {
     34    _Objects_Allocator_unlock();
     35    return RTEMS_INVALID_ID;
    4836  }
    4937
     38  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
     39  _Objects_Close( &_Barrier_Information, &the_barrier->Object );
     40  _CORE_barrier_Flush( &the_barrier->Barrier, NULL, 0, &lock_context );
     41  _Barrier_Free( the_barrier );
    5042  _Objects_Allocator_unlock();
    51 
    52   return RTEMS_INVALID_ID;
     43  return RTEMS_SUCCESSFUL;
    5344}
  • cpukit/rtems/src/barrierrelease.c

    r5c9fa6f rf27383a  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    2421#include <rtems/rtems/barrierimpl.h>
    25 #include <rtems/score/thread.h>
    26 
    27 /*
    28  *  rtems_barrier_release
    29  *
    30  *  This directive releases all threads waiting at a barrier.
    31  *
    32  *  Input parameters:
    33  *    id         - barrier id
    34  *    released   - pointer to number of threads unblocked
    35  *
    36  *  Output parameters:
    37  *    RTEMS_SUCCESSFUL - if successful
    38  *    error code       - if unsuccessful
    39  *    *released        - number of threads unblocked
    40  */
    4122
    4223rtems_status_code rtems_barrier_release(
     
    4526)
    4627{
    47   Barrier_Control   *the_barrier;
    48   Objects_Locations  location;
     28  Barrier_Control  *the_barrier;
     29  ISR_lock_Context  lock_context;
    4930
    50   if ( !released )
     31  if ( released == NULL ) {
    5132    return RTEMS_INVALID_ADDRESS;
    52 
    53   the_barrier = _Barrier_Get( id, &location );
    54   switch ( location ) {
    55 
    56     case OBJECTS_LOCAL:
    57       *released = _CORE_barrier_Surrender( &the_barrier->Barrier, NULL, 0 );
    58       _Objects_Put( &the_barrier->Object );
    59       return RTEMS_SUCCESSFUL;
    60 
    61 #if defined(RTEMS_MULTIPROCESSING)
    62     case OBJECTS_REMOTE:
    63 #endif
    64     case OBJECTS_ERROR:
    65       break;
    6633  }
    6734
    68   return RTEMS_INVALID_ID;
     35  the_barrier = _Barrier_Get( id, &lock_context );
     36
     37  if ( the_barrier == NULL ) {
     38    return RTEMS_INVALID_ID;
     39  }
     40
     41  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
     42  *released = _CORE_barrier_Surrender(
     43    &the_barrier->Barrier,
     44    NULL,
     45    0,
     46    &lock_context
     47  );
     48  return RTEMS_SUCCESSFUL;
    6949}
  • cpukit/rtems/src/barrierwait.c

    r5c9fa6f rf27383a  
    1919#endif
    2020
    21 #include <rtems/system.h>
    22 #include <rtems/rtems/status.h>
    23 #include <rtems/rtems/support.h>
    2421#include <rtems/rtems/barrierimpl.h>
    2522#include <rtems/score/threadimpl.h>
     
    3229)
    3330{
    34   Barrier_Control   *the_barrier;
    35   Objects_Locations  location;
    36   Thread_Control    *executing;
     31  Barrier_Control  *the_barrier;
     32  ISR_lock_Context  lock_context;
     33  Thread_Control   *executing;
    3734
    38   the_barrier = _Barrier_Get( id, &location );
    39   switch ( location ) {
     35  the_barrier = _Barrier_Get( id, &lock_context );
    4036
    41     case OBJECTS_LOCAL:
    42       executing = _Thread_Executing;
    43       _CORE_barrier_Seize(
    44         &the_barrier->Barrier,
    45         executing,
    46         true,
    47         timeout,
    48         NULL,
    49         0
    50       );
    51       _Objects_Put( &the_barrier->Object );
    52       return _Barrier_Translate_core_barrier_return_code(
    53                 executing->Wait.return_code );
    54 
    55 #if defined(RTEMS_MULTIPROCESSING)
    56     case OBJECTS_REMOTE:
    57 #endif
    58     case OBJECTS_ERROR:
    59       break;
     37  if ( the_barrier == NULL ) {
     38    return RTEMS_INVALID_ID;
    6039  }
    6140
    62   return RTEMS_INVALID_ID;
     41  executing = _Thread_Executing;
     42  _CORE_barrier_Seize(
     43    &the_barrier->Barrier,
     44    executing,
     45    true,
     46    timeout,
     47    NULL,
     48    0,
     49    &lock_context
     50  );
     51  return _Barrier_Translate_core_barrier_return_code(
     52    executing->Wait.return_code
     53  );
    6354}
  • cpukit/score/include/rtems/score/corebarrierimpl.h

    r5c9fa6f rf27383a  
    2121
    2222#include <rtems/score/corebarrier.h>
    23 #include <rtems/score/thread.h>
    2423#include <rtems/score/threadqimpl.h>
    25 #include <rtems/score/watchdog.h>
    2624
    2725#ifdef __cplusplus
     
    8583}
    8684
     85RTEMS_INLINE_ROUTINE void _CORE_barrier_Acquire_critical(
     86  CORE_barrier_Control *the_barrier,
     87  ISR_lock_Context     *lock_context
     88)
     89{
     90  _Thread_queue_Acquire_critical( &the_barrier->Wait_queue, lock_context );
     91}
     92
     93RTEMS_INLINE_ROUTINE void _CORE_barrier_Release(
     94  CORE_barrier_Control *the_barrier,
     95  ISR_lock_Context     *lock_context
     96)
     97{
     98  _Thread_queue_Release( &the_barrier->Wait_queue, lock_context );
     99}
     100
    87101void _CORE_barrier_Do_seize(
    88102  CORE_barrier_Control    *the_barrier,
    89103  Thread_Control          *executing,
    90104  bool                     wait,
    91   Watchdog_Interval        timeout
    92 #if defined(RTEMS_MULTIPROCESSING)
    93   ,
     105  Watchdog_Interval        timeout,
     106#if defined(RTEMS_MULTIPROCESSING)
    94107  Thread_queue_MP_callout  mp_callout,
    95   Objects_Id               mp_id
    96 #endif
     108  Objects_Id               mp_id,
     109#endif
     110  ISR_lock_Context        *lock_context
    97111);
    98112
     
    123137    timeout, \
    124138    mp_callout, \
    125     mp_id \
     139    mp_id, \
     140    lock_context \
    126141  ) \
    127142    _CORE_barrier_Do_seize( \
     
    131146      timeout, \
    132147      mp_callout, \
    133       mp_id \
     148      mp_id, \
     149      lock_context \
    134150    )
    135151#else
     
    140156    timeout, \
    141157    mp_callout, \
    142     mp_id \
     158    mp_id, \
     159    lock_context \
    143160  ) \
    144161    _CORE_barrier_Do_seize( \
     
    146163      executing, \
    147164      wait, \
    148       timeout \
     165      timeout, \
     166      lock_context \
    149167    )
    150168#endif
    151169
    152170uint32_t _CORE_barrier_Do_surrender(
    153   CORE_barrier_Control    *the_barrier
    154 #if defined(RTEMS_MULTIPROCESSING)
    155   ,
    156   Thread_queue_MP_callout  mp_callout,
    157   Objects_Id               mp_id
    158 #endif
     171  CORE_barrier_Control      *the_barrier,
     172  Thread_queue_Flush_filter  filter,
     173#if defined(RTEMS_MULTIPROCESSING)
     174  Thread_queue_MP_callout    mp_callout,
     175  Objects_Id                 mp_id,
     176#endif
     177  ISR_lock_Context          *lock_context
    159178);
    160179
     
    176195    the_barrier, \
    177196    mp_callout, \
    178     mp_id \
     197    mp_id, \
     198    lock_context \
    179199  ) \
    180200    _CORE_barrier_Do_surrender( \
    181201      the_barrier, \
    182202      mp_callout, \
    183       mp_id \
     203      mp_id, \
     204      _Thread_queue_Flush_default_filter, \
     205      lock_context \
    184206    )
    185207#else
     
    187209    the_barrier, \
    188210    mp_callout, \
    189     mp_id \
    190   ) \
    191     _CORE_barrier_Do_surrender( \
    192       the_barrier \
     211    mp_id, \
     212    lock_context \
     213  ) \
     214    _CORE_barrier_Do_surrender( \
     215      the_barrier, \
     216      _Thread_queue_Flush_default_filter, \
     217      lock_context \
    193218    )
    194219#endif
     
    201226
    202227/* Must be a macro due to the multiprocessing dependent parameters */
    203 #define _CORE_barrier_Flush( \
    204   the_barrier, \
    205   mp_callout, \
    206   mp_id \
    207 ) \
    208   do { \
    209     ISR_lock_Context _core_barrier_flush_lock_context; \
    210     _Thread_queue_Acquire( \
    211       &( the_barrier )->Wait_queue, \
    212       &_core_barrier_flush_lock_context \
    213     ); \
    214     _Thread_queue_Flush_critical( \
    215       &( the_barrier )->Wait_queue.Queue, \
    216       CORE_BARRIER_TQ_OPERATIONS, \
     228#if defined(RTEMS_MULTIPROCESSING)
     229  #define _CORE_barrier_Flush( \
     230    the_barrier, \
     231    mp_callout, \
     232    mp_id, \
     233    lock_context \
     234  ) \
     235    _CORE_barrier_Do_surrender( \
     236      the_barrier, \
    217237      _CORE_barrier_Was_deleted, \
    218238      mp_callout, \
    219239      mp_id, \
    220       &_core_barrier_flush_lock_context \
    221     ); \
    222   } while ( 0 )
     240      lock_context \
     241    )
     242#else
     243  #define _CORE_barrier_Flush( \
     244    the_barrier, \
     245    mp_callout, \
     246    mp_id, \
     247    lock_context \
     248  ) \
     249    _CORE_barrier_Do_surrender( \
     250      the_barrier, \
     251      _CORE_barrier_Was_deleted, \
     252      lock_context \
     253    )
     254#endif
    223255
    224256/**
  • cpukit/score/src/corebarrierrelease.c

    r5c9fa6f rf27383a  
    2121
    2222#include <rtems/score/corebarrierimpl.h>
    23 #include <rtems/score/objectimpl.h>
    24 #include <rtems/score/threadqimpl.h>
    2523
    2624uint32_t _CORE_barrier_Do_surrender(
    27   CORE_barrier_Control    *the_barrier
     25  CORE_barrier_Control      *the_barrier,
     26  Thread_queue_Flush_filter  filter,
    2827#if defined(RTEMS_MULTIPROCESSING)
    29   ,
    30   Thread_queue_MP_callout  mp_callout,
    31   Objects_Id               mp_id
     28  Thread_queue_MP_callout    mp_callout,
     29  Objects_Id                 mp_id,
    3230#endif
     31  ISR_lock_Context          *lock_context
    3332)
    3433{
    35   Thread_Control *the_thread;
    36   uint32_t        count;
    37 
    38   count = 0;
    39   while (
    40     (
    41       the_thread = _Thread_queue_Dequeue(
    42         &the_barrier->Wait_queue,
    43         CORE_BARRIER_TQ_OPERATIONS,
    44         mp_callout,
    45         mp_id
    46       )
    47     )
    48   ) {
    49     count++;
    50   }
    5134  the_barrier->number_of_waiting_threads = 0;
    52   return count;
     35  return _Thread_queue_Flush_critical(
     36    &the_barrier->Wait_queue.Queue,
     37    CORE_BARRIER_TQ_OPERATIONS,
     38    filter,
     39    mp_callout,
     40    mp_id,
     41    lock_context
     42  );
    5343}
  • cpukit/score/src/corebarrierwait.c

    r5c9fa6f rf27383a  
    2020
    2121#include <rtems/score/corebarrierimpl.h>
    22 #include <rtems/score/isrlevel.h>
    2322#include <rtems/score/statesimpl.h>
    24 #include <rtems/score/threadqimpl.h>
    2523
    2624void _CORE_barrier_Do_seize(
     
    2826  Thread_Control          *executing,
    2927  bool                     wait,
    30   Watchdog_Interval        timeout
     28  Watchdog_Interval        timeout,
    3129#if defined(RTEMS_MULTIPROCESSING)
    32   ,
    3330  Thread_queue_MP_callout  mp_callout,
    34   Objects_Id               mp_id
     31  Objects_Id               mp_id,
    3532#endif
     33  ISR_lock_Context        *lock_context
    3634)
    3735{
    38   ISR_lock_Context lock_context;
     36  uint32_t number_of_waiting_threads;
    3937
    4038  executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
    41   _Thread_queue_Acquire( &the_barrier->Wait_queue, &lock_context );
    42   the_barrier->number_of_waiting_threads++;
    43   if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) {
    44     if ( the_barrier->number_of_waiting_threads ==
    45          the_barrier->Attributes.maximum_count) {
    46       executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
    47       _Thread_queue_Release( &the_barrier->Wait_queue, &lock_context );
    48       _CORE_barrier_Surrender( the_barrier, mp_callout, mp_id );
    49       return;
    50     }
     39
     40  _CORE_barrier_Acquire_critical( the_barrier, lock_context );
     41
     42  number_of_waiting_threads = the_barrier->number_of_waiting_threads;
     43  ++number_of_waiting_threads;
     44
     45  if (
     46    _CORE_barrier_Is_automatic( &the_barrier->Attributes )
     47      && number_of_waiting_threads == the_barrier->Attributes.maximum_count
     48  ) {
     49    executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
     50    _CORE_barrier_Surrender( the_barrier, mp_callout, mp_id, lock_context );
     51  } else {
     52    the_barrier->number_of_waiting_threads = number_of_waiting_threads;
     53    _Thread_queue_Enqueue_critical(
     54      &the_barrier->Wait_queue.Queue,
     55      CORE_BARRIER_TQ_OPERATIONS,
     56      executing,
     57      STATES_WAITING_FOR_BARRIER,
     58      timeout,
     59      CORE_BARRIER_TIMEOUT,
     60      lock_context
     61    );
    5162  }
    52 
    53   _Thread_queue_Enqueue_critical(
    54     &the_barrier->Wait_queue.Queue,
    55     CORE_BARRIER_TQ_OPERATIONS,
    56     executing,
    57     STATES_WAITING_FOR_BARRIER,
    58     timeout,
    59     CORE_BARRIER_TIMEOUT,
    60     &lock_context
    61   );
    6263}
Note: See TracChangeset for help on using the changeset viewer.