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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel