From 3cbdf19eacf45a8e9faad284b71775a9d56872dd Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sun, 21 Feb 2021 10:21:26 +0100 Subject: score: Simplify core barrier Use the number of threads which must arrive at the barrier to trip the automatic release also to indicate if the barrier is a manual release barrier. --- cpukit/include/rtems/score/corebarrier.h | 56 +++++++++------------------- cpukit/include/rtems/score/corebarrierimpl.h | 56 +++++++--------------------- cpukit/rtems/src/barriercreate.c | 29 +++++++------- cpukit/score/src/corebarrier.c | 7 ++-- cpukit/score/src/corebarrierwait.c | 17 +++++---- 5 files changed, 59 insertions(+), 106 deletions(-) (limited to 'cpukit') diff --git a/cpukit/include/rtems/score/corebarrier.h b/cpukit/include/rtems/score/corebarrier.h index 60abbd6f8f..7cfaeddca7 100644 --- a/cpukit/include/rtems/score/corebarrier.h +++ b/cpukit/include/rtems/score/corebarrier.h @@ -40,50 +40,30 @@ extern "C" { */ /** - * Flavors of barriers. - */ -typedef enum { - /** This specifies that the barrier will automatically release when - * the user specified number of threads have arrived at the barrier. - */ - CORE_BARRIER_AUTOMATIC_RELEASE, - /** This specifies that the user will have to manually release the barrier - * in order to release the waiting threads. - */ - CORE_BARRIER_MANUAL_RELEASE -} CORE_barrier_Disciplines; - -/** - * The following defines the control block used to manage the - * attributes of each barrier. + * @brief This control block is used to manage a barrier. */ typedef struct { - /** This field indicates whether the barrier is automatic or manual. + /** + * @brief This member is used to manage the set of tasks which are + * blocked waiting for the barrier to be released. */ - CORE_barrier_Disciplines discipline; - /** This element indicates the number of threads which must arrive at the - * barrier to trip the automatic release. - */ - uint32_t maximum_count; -} CORE_barrier_Attributes; + Thread_queue_Control Wait_queue; -/** - * The following defines the control block used to manage each - * barrier. - */ -typedef struct { - /** This field is the Waiting Queue used to manage the set of tasks - * which are blocked waiting for the barrier to be released. + /** + * @brief This member contains the current number of thread waiting at the + * barrier to be released. */ - Thread_queue_Control Wait_queue; - /** This element is the set of attributes which define this instance's - * behavior. + uint32_t number_of_waiting_threads; + + /** + * @brief This member indicates the number of threads which must arrive at + * the barrier to trip the automatic release. + * + * Use ::CORE_BARRIER_MANUAL_RELEASE_MAXIMUM_COUNT to indicate a manual + * release barrier. */ - CORE_barrier_Attributes Attributes; - /** This element contains the current number of thread waiting for this - * barrier to be released. */ - uint32_t number_of_waiting_threads; -} CORE_barrier_Control; + uint32_t maximum_count; +} CORE_barrier_Control; /** @} */ diff --git a/cpukit/include/rtems/score/corebarrierimpl.h b/cpukit/include/rtems/score/corebarrierimpl.h index 922eb5d28f..86a3e956dc 100644 --- a/cpukit/include/rtems/score/corebarrierimpl.h +++ b/cpukit/include/rtems/score/corebarrierimpl.h @@ -33,6 +33,12 @@ extern "C" { * @{ */ +/** + * @brief This maximum thread count constant indicates that the barrier is a + * manual release barrier. + */ +#define CORE_BARRIER_MANUAL_RELEASE_MAXIMUM_COUNT 0 + /** * @brief These thread queue operations are used for core barriers. * @@ -43,16 +49,18 @@ extern "C" { extern const Thread_queue_Operations _CORE_barrier_Thread_queue_operations; /** - * @brief Initializes the core barrier. + * @brief Initializes the core barrier. * - * This routine initializes the barrier based on the parameters passed. + * @param[out] the_barrier is the barrier to initialize. * - * @param[out] the_barrier The barrier to initialize. - * @param[out] the_barrier_attributes The attributes which define the behavior of this instance. + * @param maximum_count is the number of threads which must arrive at the + * barrier to trip the automatic release or + * ::CORE_BARRIER_MANUAL_RELEASE_MAXIMUM_COUNT to indicate a manual release + * barrier. */ void _CORE_barrier_Initialize( - CORE_barrier_Control *the_barrier, - CORE_barrier_Attributes *the_barrier_attributes + CORE_barrier_Control *the_barrier, + uint32_t maximum_count ); /** @@ -173,42 +181,6 @@ RTEMS_INLINE_ROUTINE void _CORE_barrier_Flush( ); } -/** - * @brief Checks if the barrier is automatic. - * - * This function returns true if the automatic release attribute is - * enabled in the @a attribute_set and false otherwise. - * - * @param the_attribute The attribute set to test. - * - * @retval true The automatic release attribute is enabled. - * @retval false The automatic release attribute is not enabled. - */ -RTEMS_INLINE_ROUTINE bool _CORE_barrier_Is_automatic( - CORE_barrier_Attributes *the_attribute -) -{ - return - (the_attribute->discipline == CORE_BARRIER_AUTOMATIC_RELEASE); -} - -/** - * @brief Returns the number of currently waiting threads. - * - * This routine returns the number of threads currently waiting at the barrier. - * - * @param[in] the_barrier The barrier to obtain the number of blocked - * threads of. - * - * @return the current count of waiting threads of this barrier. - */ -RTEMS_INLINE_ROUTINE uint32_t _CORE_barrier_Get_number_of_waiting_threads( - CORE_barrier_Control *the_barrier -) -{ - return the_barrier->number_of_waiting_threads; -} - /** @} */ #ifdef __cplusplus diff --git a/cpukit/rtems/src/barriercreate.c b/cpukit/rtems/src/barriercreate.c index 99d916d8c7..80b10e1e0b 100644 --- a/cpukit/rtems/src/barriercreate.c +++ b/cpukit/rtems/src/barriercreate.c @@ -34,34 +34,35 @@ rtems_status_code rtems_barrier_create( rtems_id *id ) { - Barrier_Control *the_barrier; - CORE_barrier_Attributes the_attributes; + Barrier_Control *the_barrier; + uint32_t maximum_count; - if ( !rtems_is_name_valid( name ) ) + if ( !rtems_is_name_valid( name ) ) { return RTEMS_INVALID_NAME; + } - if ( !id ) + if ( id == NULL ) { return RTEMS_INVALID_ADDRESS; + } - /* Initialize core barrier attributes */ if ( _Attributes_Is_barrier_automatic( attribute_set ) ) { - the_attributes.discipline = CORE_BARRIER_AUTOMATIC_RELEASE; - if ( maximum_waiters == 0 ) + if ( maximum_waiters == 0 ) { return RTEMS_INVALID_NUMBER; - } else - the_attributes.discipline = CORE_BARRIER_MANUAL_RELEASE; - the_attributes.maximum_count = maximum_waiters; + } + + maximum_count = maximum_waiters; + } else { + maximum_count = CORE_BARRIER_MANUAL_RELEASE_MAXIMUM_COUNT; + } the_barrier = _Barrier_Allocate(); - if ( !the_barrier ) { + if ( the_barrier == NULL ) { _Objects_Allocator_unlock(); return RTEMS_TOO_MANY; } - the_barrier->attribute_set = attribute_set; - - _CORE_barrier_Initialize( &the_barrier->Barrier, &the_attributes ); + _CORE_barrier_Initialize( &the_barrier->Barrier, maximum_count ); *id = _Objects_Open_u32( &_Barrier_Information, &the_barrier->Object, name ); _Objects_Allocator_unlock(); diff --git a/cpukit/score/src/corebarrier.c b/cpukit/score/src/corebarrier.c index c9c9b04ed5..edb37d7087 100644 --- a/cpukit/score/src/corebarrier.c +++ b/cpukit/score/src/corebarrier.c @@ -23,13 +23,12 @@ #include void _CORE_barrier_Initialize( - CORE_barrier_Control *the_barrier, - CORE_barrier_Attributes *the_barrier_attributes + CORE_barrier_Control *the_barrier, + uint32_t maximum_count ) { - - the_barrier->Attributes = *the_barrier_attributes; the_barrier->number_of_waiting_threads = 0; + the_barrier->maximum_count = maximum_count; _Thread_queue_Object_initialize( &the_barrier->Wait_queue ); } diff --git a/cpukit/score/src/corebarrierwait.c b/cpukit/score/src/corebarrierwait.c index 197e0cf405..078276bf05 100644 --- a/cpukit/score/src/corebarrierwait.c +++ b/cpukit/score/src/corebarrierwait.c @@ -61,21 +61,22 @@ Status_Control _CORE_barrier_Seize( Thread_queue_Context *queue_context ) { - uint32_t number_of_waiting_threads; + uint32_t new_number_of_waiting_threads; _CORE_barrier_Acquire_critical( the_barrier, queue_context ); - number_of_waiting_threads = the_barrier->number_of_waiting_threads; - ++number_of_waiting_threads; + /* + * In theory, this calculation can overflow. If this happens, then about 4 + * billion threads are accidentally released. Currently, the system limit + * for threads is a bit lower with three times OBJECTS_INDEX_MASK - 1. + */ + new_number_of_waiting_threads = the_barrier->number_of_waiting_threads + 1; - if ( - _CORE_barrier_Is_automatic( &the_barrier->Attributes ) - && number_of_waiting_threads == the_barrier->Attributes.maximum_count - ) { + if ( new_number_of_waiting_threads == the_barrier->maximum_count ) { _CORE_barrier_Surrender( the_barrier, queue_context ); return STATUS_BARRIER_AUTOMATICALLY_RELEASED; } else { - the_barrier->number_of_waiting_threads = number_of_waiting_threads; + the_barrier->number_of_waiting_threads = new_number_of_waiting_threads; _Thread_queue_Context_set_thread_state( queue_context, STATES_WAITING_FOR_BARRIER -- cgit v1.2.3