[PATCH 08/10] score: Avoid Giant lock for barriers

Sebastian Huber sebastian.huber at embedded-brains.de
Thu Apr 21 07:20:12 UTC 2016


Use _Thread_queue_Flush_critical() to atomically release the barrier.

Update #2555.
---
 cpukit/posix/include/rtems/posix/barrierimpl.h     |  24 ++---
 cpukit/posix/src/pbarrierdestroy.c                 |  45 ++++------
 cpukit/posix/src/pbarrierwait.c                    |  50 +++++------
 cpukit/rtems/include/rtems/rtems/barrierimpl.h     |  19 +---
 cpukit/rtems/src/barrierdelete.c                   |  31 +++----
 cpukit/rtems/src/barrierrelease.c                  |  50 ++++-------
 cpukit/rtems/src/barrierwait.c                     |  51 +++++------
 cpukit/score/include/rtems/score/corebarrierimpl.h | 100 ++++++++++++++-------
 cpukit/score/src/corebarrierrelease.c              |  36 +++-----
 cpukit/score/src/corebarrierwait.c                 |  53 +++++------
 10 files changed, 203 insertions(+), 256 deletions(-)

diff --git a/cpukit/posix/include/rtems/posix/barrierimpl.h b/cpukit/posix/include/rtems/posix/barrierimpl.h
index 646b734..16ccdc5 100644
--- a/cpukit/posix/include/rtems/posix/barrierimpl.h
+++ b/cpukit/posix/include/rtems/posix/barrierimpl.h
@@ -23,6 +23,7 @@
 #include <rtems/score/corebarrierimpl.h>
 #include <rtems/score/objectimpl.h>
 
+#include <errno.h>
 #include <pthread.h>
 
 #ifdef __cplusplus
@@ -76,26 +77,15 @@ RTEMS_INLINE_ROUTINE void _POSIX_Barrier_Free (
   _Objects_Free( &_POSIX_Barrier_Information, &the_barrier->Object );
 }
 
-/**
- * @brief Get a barrier control block.
- *
- * This function maps barrier IDs to barrier control blocks.
- * If ID corresponds to a local barrier, then it returns
- * the_barrier control pointer which maps to ID and location
- * is set to OBJECTS_LOCAL.  if the barrier ID is global and
- * resides on a remote node, then location is set to OBJECTS_REMOTE,
- * and the_barrier is undefined.  Otherwise, location is set
- * to OBJECTS_ERROR and the_barrier is undefined.
- */
 RTEMS_INLINE_ROUTINE POSIX_Barrier_Control *_POSIX_Barrier_Get (
-  pthread_barrier_t *barrier,
-  Objects_Locations *location
+  const pthread_barrier_t *barrier,
+  ISR_lock_Context        *lock_context
 )
 {
-  return (POSIX_Barrier_Control *) _Objects_Get(
-      &_POSIX_Barrier_Information,
-      (Objects_Id) *barrier,
-      location
+  return (POSIX_Barrier_Control *) _Objects_Get_local(
+    (Objects_Id) *barrier,
+    &_POSIX_Barrier_Information,
+    lock_context
   );
 }
 
diff --git a/cpukit/posix/src/pbarrierdestroy.c b/cpukit/posix/src/pbarrierdestroy.c
index 4b9a0fd..709644b 100644
--- a/cpukit/posix/src/pbarrierdestroy.c
+++ b/cpukit/posix/src/pbarrierdestroy.c
@@ -18,10 +18,6 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
-#include <rtems/system.h>
 #include <rtems/posix/barrierimpl.h>
 
 /**
@@ -39,37 +35,32 @@ int pthread_barrier_destroy(
   pthread_barrier_t *barrier
 )
 {
-  POSIX_Barrier_Control *the_barrier = NULL;
-  Objects_Locations      location;
+  POSIX_Barrier_Control *the_barrier;
+  ISR_lock_Context       lock_context;
 
-  if ( !barrier )
+  if ( barrier == NULL ) {
     return EINVAL;
+  }
 
   _Objects_Allocator_lock();
-  the_barrier = _POSIX_Barrier_Get( barrier, &location );
-  switch ( location ) {
+  the_barrier = _POSIX_Barrier_Get( barrier, &lock_context );
 
-    case OBJECTS_LOCAL:
-      if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) {
-        _Objects_Put( &the_barrier->Object );
-        return EBUSY;
-      }
-
-      _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object );
-      _Objects_Put( &the_barrier->Object );
+  if ( the_barrier == NULL ) {
+    _Objects_Allocator_unlock();
+    return EINVAL;
+  }
 
-      _POSIX_Barrier_Free( the_barrier );
-      _Objects_Allocator_unlock();
-      return 0;
+  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
 
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  if ( the_barrier->Barrier.number_of_waiting_threads != 0 ) {
+    _CORE_barrier_Release( &the_barrier->Barrier, &lock_context );
+    _Objects_Allocator_unlock();
+    return EBUSY;
   }
 
+  _Objects_Close( &_POSIX_Barrier_Information, &the_barrier->Object );
+  _CORE_barrier_Release( &the_barrier->Barrier, &lock_context );
+  _POSIX_Barrier_Free( the_barrier );
   _Objects_Allocator_unlock();
-
-  return EINVAL;
+  return 0;
 }
diff --git a/cpukit/posix/src/pbarrierwait.c b/cpukit/posix/src/pbarrierwait.c
index 86bfba7..9200dc0 100644
--- a/cpukit/posix/src/pbarrierwait.c
+++ b/cpukit/posix/src/pbarrierwait.c
@@ -18,9 +18,6 @@
 #include "config.h"
 #endif
 
-#include <pthread.h>
-#include <errno.h>
-
 #include <rtems/posix/barrierimpl.h>
 #include <rtems/score/threadimpl.h>
 
@@ -40,36 +37,31 @@ int pthread_barrier_wait(
   pthread_barrier_t *barrier
 )
 {
-  POSIX_Barrier_Control   *the_barrier = NULL;
-  Objects_Locations        location;
-  Thread_Control          *executing;
+  POSIX_Barrier_Control *the_barrier;
+  ISR_lock_Context       lock_context;
+  Thread_Control        *executing;
 
-  if ( !barrier )
+  if ( barrier == NULL ) {
     return EINVAL;
+  }
 
-  the_barrier = _POSIX_Barrier_Get( barrier, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      executing = _Thread_Executing;
-      _CORE_barrier_Seize(
-        &the_barrier->Barrier,
-        executing,
-        true,
-        0,
-        NULL,
-        0
-      );
-      _Objects_Put( &the_barrier->Object );
-      return _POSIX_Barrier_Translate_core_barrier_return_code(
-                executing->Wait.return_code );
+  the_barrier = _POSIX_Barrier_Get( barrier, &lock_context );
 
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  if ( the_barrier == NULL ) {
+    return EINVAL;
   }
 
-  return EINVAL;
+  executing = _Thread_Executing;
+  _CORE_barrier_Seize(
+    &the_barrier->Barrier,
+    executing,
+    true,
+    0,
+    NULL,
+    0,
+    &lock_context
+  );
+  return _POSIX_Barrier_Translate_core_barrier_return_code(
+    executing->Wait.return_code
+  );
 }
diff --git a/cpukit/rtems/include/rtems/rtems/barrierimpl.h b/cpukit/rtems/include/rtems/rtems/barrierimpl.h
index 9b22a32..1598ce2 100644
--- a/cpukit/rtems/include/rtems/rtems/barrierimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/barrierimpl.h
@@ -69,24 +69,13 @@ RTEMS_INLINE_ROUTINE void _Barrier_Free (
   _Objects_Free( &_Barrier_Information, &the_barrier->Object );
 }
 
-/**
- *  @brief _Barrier_Get
- *
- *  This function maps barrier IDs to barrier control blocks.
- *  If ID corresponds to a local barrier, then it returns
- *  the_barrier control pointer which maps to ID and location
- *  is set to OBJECTS_LOCAL.  if the barrier ID is global and
- *  resides on a remote node, then location is set to OBJECTS_REMOTE,
- *  and the_barrier is undefined.  Otherwise, location is set
- *  to OBJECTS_ERROR and the_barrier is undefined.
- */
-RTEMS_INLINE_ROUTINE Barrier_Control *_Barrier_Get (
-  Objects_Id         id,
-  Objects_Locations *location
+RTEMS_INLINE_ROUTINE Barrier_Control *_Barrier_Get(
+  Objects_Id        id,
+  ISR_lock_Context *lock_context
 )
 {
   return (Barrier_Control *)
-    _Objects_Get( &_Barrier_Information, id, location );
+    _Objects_Get_local( id, &_Barrier_Information, lock_context );
 }
 
 /**
diff --git a/cpukit/rtems/src/barrierdelete.c b/cpukit/rtems/src/barrierdelete.c
index 5d87e63..d742327 100644
--- a/cpukit/rtems/src/barrierdelete.c
+++ b/cpukit/rtems/src/barrierdelete.c
@@ -19,35 +19,26 @@
 #endif
 
 #include <rtems/rtems/barrierimpl.h>
-#include <rtems/score/threadqimpl.h>
 
 rtems_status_code rtems_barrier_delete(
   rtems_id   id
 )
 {
-  Barrier_Control   *the_barrier;
-  Objects_Locations  location;
+  Barrier_Control  *the_barrier;
+  ISR_lock_Context  lock_context;
 
   _Objects_Allocator_lock();
-  the_barrier = _Barrier_Get( id, &location );
-  switch ( location ) {
+  the_barrier = _Barrier_Get( id, &lock_context );
 
-    case OBJECTS_LOCAL:
-      _Objects_Close( &_Barrier_Information, &the_barrier->Object );
-      _CORE_barrier_Flush( &the_barrier->Barrier, NULL, 0 );
-      _Objects_Put( &the_barrier->Object );
-      _Barrier_Free( the_barrier );
-      _Objects_Allocator_unlock();
-      return RTEMS_SUCCESSFUL;
-
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  if ( the_barrier == NULL ) {
+    _Objects_Allocator_unlock();
+    return RTEMS_INVALID_ID;
   }
 
+  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
+  _Objects_Close( &_Barrier_Information, &the_barrier->Object );
+  _CORE_barrier_Flush( &the_barrier->Barrier, NULL, 0, &lock_context );
+  _Barrier_Free( the_barrier );
   _Objects_Allocator_unlock();
-
-  return RTEMS_INVALID_ID;
+  return RTEMS_SUCCESSFUL;
 }
diff --git a/cpukit/rtems/src/barrierrelease.c b/cpukit/rtems/src/barrierrelease.c
index 77937b3..a60ea89 100644
--- a/cpukit/rtems/src/barrierrelease.c
+++ b/cpukit/rtems/src/barrierrelease.c
@@ -18,52 +18,32 @@
 #include "config.h"
 #endif
 
-#include <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
 #include <rtems/rtems/barrierimpl.h>
-#include <rtems/score/thread.h>
-
-/*
- *  rtems_barrier_release
- *
- *  This directive releases all threads waiting at a barrier.
- *
- *  Input parameters:
- *    id         - barrier id
- *    released   - pointer to number of threads unblocked
- *
- *  Output parameters:
- *    RTEMS_SUCCESSFUL - if successful
- *    error code       - if unsuccessful
- *    *released        - number of threads unblocked
- */
 
 rtems_status_code rtems_barrier_release(
   rtems_id          id,
   uint32_t         *released
 )
 {
-  Barrier_Control   *the_barrier;
-  Objects_Locations  location;
+  Barrier_Control  *the_barrier;
+  ISR_lock_Context  lock_context;
 
-  if ( !released )
+  if ( released == NULL ) {
     return RTEMS_INVALID_ADDRESS;
+  }
 
-  the_barrier = _Barrier_Get( id, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      *released = _CORE_barrier_Surrender( &the_barrier->Barrier, NULL, 0 );
-      _Objects_Put( &the_barrier->Object );
-      return RTEMS_SUCCESSFUL;
+  the_barrier = _Barrier_Get( id, &lock_context );
 
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  if ( the_barrier == NULL ) {
+    return RTEMS_INVALID_ID;
   }
 
-  return RTEMS_INVALID_ID;
+  _CORE_barrier_Acquire_critical( &the_barrier->Barrier, &lock_context );
+  *released = _CORE_barrier_Surrender(
+    &the_barrier->Barrier,
+    NULL,
+    0,
+    &lock_context
+  );
+  return RTEMS_SUCCESSFUL;
 }
diff --git a/cpukit/rtems/src/barrierwait.c b/cpukit/rtems/src/barrierwait.c
index f8f9ac3..b5f23d7 100644
--- a/cpukit/rtems/src/barrierwait.c
+++ b/cpukit/rtems/src/barrierwait.c
@@ -18,9 +18,6 @@
 #include "config.h"
 #endif
 
-#include <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
 #include <rtems/rtems/barrierimpl.h>
 #include <rtems/score/threadimpl.h>
 
@@ -31,33 +28,27 @@ rtems_status_code rtems_barrier_wait(
   rtems_interval  timeout
 )
 {
-  Barrier_Control   *the_barrier;
-  Objects_Locations  location;
-  Thread_Control    *executing;
-
-  the_barrier = _Barrier_Get( id, &location );
-  switch ( location ) {
-
-    case OBJECTS_LOCAL:
-      executing = _Thread_Executing;
-      _CORE_barrier_Seize(
-        &the_barrier->Barrier,
-        executing,
-        true,
-        timeout,
-        NULL,
-        0
-      );
-      _Objects_Put( &the_barrier->Object );
-      return _Barrier_Translate_core_barrier_return_code(
-                executing->Wait.return_code );
-
-#if defined(RTEMS_MULTIPROCESSING)
-    case OBJECTS_REMOTE:
-#endif
-    case OBJECTS_ERROR:
-      break;
+  Barrier_Control  *the_barrier;
+  ISR_lock_Context  lock_context;
+  Thread_Control   *executing;
+
+  the_barrier = _Barrier_Get( id, &lock_context );
+
+  if ( the_barrier == NULL ) {
+    return RTEMS_INVALID_ID;
   }
 
-  return RTEMS_INVALID_ID;
+  executing = _Thread_Executing;
+  _CORE_barrier_Seize(
+    &the_barrier->Barrier,
+    executing,
+    true,
+    timeout,
+    NULL,
+    0,
+    &lock_context
+  );
+  return _Barrier_Translate_core_barrier_return_code(
+    executing->Wait.return_code
+  );
 }
diff --git a/cpukit/score/include/rtems/score/corebarrierimpl.h b/cpukit/score/include/rtems/score/corebarrierimpl.h
index 454c2c9..7dba5de 100644
--- a/cpukit/score/include/rtems/score/corebarrierimpl.h
+++ b/cpukit/score/include/rtems/score/corebarrierimpl.h
@@ -20,9 +20,7 @@
 #define _RTEMS_SCORE_COREBARRIERIMPL_H
 
 #include <rtems/score/corebarrier.h>
-#include <rtems/score/thread.h>
 #include <rtems/score/threadqimpl.h>
-#include <rtems/score/watchdog.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -84,16 +82,32 @@ RTEMS_INLINE_ROUTINE void _CORE_barrier_Destroy(
   _Thread_queue_Destroy( &the_barrier->Wait_queue );
 }
 
+RTEMS_INLINE_ROUTINE void _CORE_barrier_Acquire_critical(
+  CORE_barrier_Control *the_barrier,
+  ISR_lock_Context     *lock_context
+)
+{
+  _Thread_queue_Acquire_critical( &the_barrier->Wait_queue, lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _CORE_barrier_Release(
+  CORE_barrier_Control *the_barrier,
+  ISR_lock_Context     *lock_context
+)
+{
+  _Thread_queue_Release( &the_barrier->Wait_queue, lock_context );
+}
+
 void _CORE_barrier_Do_seize(
   CORE_barrier_Control    *the_barrier,
   Thread_Control          *executing,
   bool                     wait,
-  Watchdog_Interval        timeout
+  Watchdog_Interval        timeout,
 #if defined(RTEMS_MULTIPROCESSING)
-  ,
   Thread_queue_MP_callout  mp_callout,
-  Objects_Id               mp_id
+  Objects_Id               mp_id,
 #endif
+  ISR_lock_Context        *lock_context
 );
 
 /**
@@ -122,7 +136,8 @@ void _CORE_barrier_Do_seize(
     wait, \
     timeout, \
     mp_callout, \
-    mp_id \
+    mp_id, \
+    lock_context \
   ) \
     _CORE_barrier_Do_seize( \
       the_barrier, \
@@ -130,7 +145,8 @@ void _CORE_barrier_Do_seize(
       wait, \
       timeout, \
       mp_callout, \
-      mp_id \
+      mp_id, \
+      lock_context \
     )
 #else
   #define _CORE_barrier_Seize( \
@@ -139,23 +155,26 @@ void _CORE_barrier_Do_seize(
     wait, \
     timeout, \
     mp_callout, \
-    mp_id \
+    mp_id, \
+    lock_context \
   ) \
     _CORE_barrier_Do_seize( \
       the_barrier, \
       executing, \
       wait, \
-      timeout \
+      timeout, \
+      lock_context \
     )
 #endif
 
 uint32_t _CORE_barrier_Do_surrender(
-  CORE_barrier_Control    *the_barrier
+  CORE_barrier_Control      *the_barrier,
+  Thread_queue_Flush_filter  filter,
 #if defined(RTEMS_MULTIPROCESSING)
-  ,
-  Thread_queue_MP_callout  mp_callout,
-  Objects_Id               mp_id
+  Thread_queue_MP_callout    mp_callout,
+  Objects_Id                 mp_id,
 #endif
+  ISR_lock_Context          *lock_context
 );
 
 /**
@@ -175,21 +194,27 @@ uint32_t _CORE_barrier_Do_surrender(
   #define _CORE_barrier_Surrender( \
     the_barrier, \
     mp_callout, \
-    mp_id \
+    mp_id, \
+    lock_context \
   ) \
     _CORE_barrier_Do_surrender( \
       the_barrier, \
       mp_callout, \
-      mp_id \
+      mp_id, \
+      _Thread_queue_Flush_default_filter, \
+      lock_context \
     )
 #else
   #define _CORE_barrier_Surrender( \
     the_barrier, \
     mp_callout, \
-    mp_id \
+    mp_id, \
+    lock_context \
   ) \
     _CORE_barrier_Do_surrender( \
-      the_barrier \
+      the_barrier, \
+      _Thread_queue_Flush_default_filter, \
+      lock_context \
     )
 #endif
 
@@ -200,26 +225,33 @@ Thread_Control *_CORE_barrier_Was_deleted(
 );
 
 /* Must be a macro due to the multiprocessing dependent parameters */
-#define _CORE_barrier_Flush( \
-  the_barrier, \
-  mp_callout, \
-  mp_id \
-) \
-  do { \
-    ISR_lock_Context _core_barrier_flush_lock_context; \
-    _Thread_queue_Acquire( \
-      &( the_barrier )->Wait_queue, \
-      &_core_barrier_flush_lock_context \
-    ); \
-    _Thread_queue_Flush_critical( \
-      &( the_barrier )->Wait_queue.Queue, \
-      CORE_BARRIER_TQ_OPERATIONS, \
+#if defined(RTEMS_MULTIPROCESSING)
+  #define _CORE_barrier_Flush( \
+    the_barrier, \
+    mp_callout, \
+    mp_id, \
+    lock_context \
+  ) \
+    _CORE_barrier_Do_surrender( \
+      the_barrier, \
       _CORE_barrier_Was_deleted, \
       mp_callout, \
       mp_id, \
-      &_core_barrier_flush_lock_context \
-    ); \
-  } while ( 0 )
+      lock_context \
+    )
+#else
+  #define _CORE_barrier_Flush( \
+    the_barrier, \
+    mp_callout, \
+    mp_id, \
+    lock_context \
+  ) \
+    _CORE_barrier_Do_surrender( \
+      the_barrier, \
+      _CORE_barrier_Was_deleted, \
+      lock_context \
+    )
+#endif
 
 /**
  * This function returns true if the automatic release attribute is
diff --git a/cpukit/score/src/corebarrierrelease.c b/cpukit/score/src/corebarrierrelease.c
index 6d72203..e6ef335 100644
--- a/cpukit/score/src/corebarrierrelease.c
+++ b/cpukit/score/src/corebarrierrelease.c
@@ -20,34 +20,24 @@
 #endif
 
 #include <rtems/score/corebarrierimpl.h>
-#include <rtems/score/objectimpl.h>
-#include <rtems/score/threadqimpl.h>
 
 uint32_t _CORE_barrier_Do_surrender(
-  CORE_barrier_Control    *the_barrier
+  CORE_barrier_Control      *the_barrier,
+  Thread_queue_Flush_filter  filter,
 #if defined(RTEMS_MULTIPROCESSING)
-  ,
-  Thread_queue_MP_callout  mp_callout,
-  Objects_Id               mp_id
+  Thread_queue_MP_callout    mp_callout,
+  Objects_Id                 mp_id,
 #endif
+  ISR_lock_Context          *lock_context
 )
 {
-  Thread_Control *the_thread;
-  uint32_t        count;
-
-  count = 0;
-  while (
-    (
-      the_thread = _Thread_queue_Dequeue(
-        &the_barrier->Wait_queue,
-        CORE_BARRIER_TQ_OPERATIONS,
-        mp_callout,
-        mp_id
-      )
-    )
-  ) {
-    count++;
-  }
   the_barrier->number_of_waiting_threads = 0;
-  return count;
+  return _Thread_queue_Flush_critical(
+    &the_barrier->Wait_queue.Queue,
+    CORE_BARRIER_TQ_OPERATIONS,
+    filter,
+    mp_callout,
+    mp_id,
+    lock_context
+  );
 }
diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c
index 11495e5..4a924b2 100644
--- a/cpukit/score/src/corebarrierwait.c
+++ b/cpukit/score/src/corebarrierwait.c
@@ -19,44 +19,45 @@
 #endif
 
 #include <rtems/score/corebarrierimpl.h>
-#include <rtems/score/isrlevel.h>
 #include <rtems/score/statesimpl.h>
-#include <rtems/score/threadqimpl.h>
 
 void _CORE_barrier_Do_seize(
   CORE_barrier_Control    *the_barrier,
   Thread_Control          *executing,
   bool                     wait,
-  Watchdog_Interval        timeout
+  Watchdog_Interval        timeout,
 #if defined(RTEMS_MULTIPROCESSING)
-  ,
   Thread_queue_MP_callout  mp_callout,
-  Objects_Id               mp_id
+  Objects_Id               mp_id,
 #endif
+  ISR_lock_Context        *lock_context
 )
 {
-  ISR_lock_Context lock_context;
+  uint32_t number_of_waiting_threads;
 
   executing->Wait.return_code = CORE_BARRIER_STATUS_SUCCESSFUL;
-  _Thread_queue_Acquire( &the_barrier->Wait_queue, &lock_context );
-  the_barrier->number_of_waiting_threads++;
-  if ( _CORE_barrier_Is_automatic( &the_barrier->Attributes ) ) {
-    if ( the_barrier->number_of_waiting_threads ==
-	 the_barrier->Attributes.maximum_count) {
-      executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
-      _Thread_queue_Release( &the_barrier->Wait_queue, &lock_context );
-      _CORE_barrier_Surrender( the_barrier, mp_callout, mp_id );
-      return;
-    }
-  }
 
-  _Thread_queue_Enqueue_critical(
-    &the_barrier->Wait_queue.Queue,
-    CORE_BARRIER_TQ_OPERATIONS,
-    executing,
-    STATES_WAITING_FOR_BARRIER,
-    timeout,
-    CORE_BARRIER_TIMEOUT,
-    &lock_context
-  );
+  _CORE_barrier_Acquire_critical( the_barrier, lock_context );
+
+  number_of_waiting_threads = the_barrier->number_of_waiting_threads;
+  ++number_of_waiting_threads;
+
+  if (
+    _CORE_barrier_Is_automatic( &the_barrier->Attributes )
+      && number_of_waiting_threads == the_barrier->Attributes.maximum_count
+  ) {
+    executing->Wait.return_code = CORE_BARRIER_STATUS_AUTOMATICALLY_RELEASED;
+    _CORE_barrier_Surrender( the_barrier, mp_callout, mp_id, lock_context );
+  } else {
+    the_barrier->number_of_waiting_threads = number_of_waiting_threads;
+    _Thread_queue_Enqueue_critical(
+      &the_barrier->Wait_queue.Queue,
+      CORE_BARRIER_TQ_OPERATIONS,
+      executing,
+      STATES_WAITING_FOR_BARRIER,
+      timeout,
+      CORE_BARRIER_TIMEOUT,
+      lock_context
+    );
+  }
 }
-- 
1.8.4.5




More information about the devel mailing list