forked from Imagelibrary/rtems
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.
This commit is contained in:
@@ -40,50 +40,30 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flavors of barriers.
|
* @brief This control block is used to manage a barrier.
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
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;
|
Thread_queue_Control Wait_queue;
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The following defines the control block used to manage each
|
* @brief This member contains the current number of thread waiting at the
|
||||||
* barrier.
|
* barrier to be released.
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
Thread_queue_Control Wait_queue;
|
uint32_t number_of_waiting_threads;
|
||||||
/** This element is the set of attributes which define this instance's
|
|
||||||
* behavior.
|
/**
|
||||||
|
* @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;
|
uint32_t maximum_count;
|
||||||
/** This element contains the current number of thread waiting for this
|
} CORE_barrier_Control;
|
||||||
* barrier to be released. */
|
|
||||||
uint32_t number_of_waiting_threads;
|
|
||||||
} CORE_barrier_Control;
|
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* @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;
|
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 maximum_count is the number of threads which must arrive at the
|
||||||
* @param[out] the_barrier_attributes The attributes which define the behavior of this instance.
|
* barrier to trip the automatic release or
|
||||||
|
* ::CORE_BARRIER_MANUAL_RELEASE_MAXIMUM_COUNT to indicate a manual release
|
||||||
|
* barrier.
|
||||||
*/
|
*/
|
||||||
void _CORE_barrier_Initialize(
|
void _CORE_barrier_Initialize(
|
||||||
CORE_barrier_Control *the_barrier,
|
CORE_barrier_Control *the_barrier,
|
||||||
CORE_barrier_Attributes *the_barrier_attributes
|
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
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -34,34 +34,35 @@ rtems_status_code rtems_barrier_create(
|
|||||||
rtems_id *id
|
rtems_id *id
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
Barrier_Control *the_barrier;
|
Barrier_Control *the_barrier;
|
||||||
CORE_barrier_Attributes the_attributes;
|
uint32_t maximum_count;
|
||||||
|
|
||||||
if ( !rtems_is_name_valid( name ) )
|
if ( !rtems_is_name_valid( name ) ) {
|
||||||
return RTEMS_INVALID_NAME;
|
return RTEMS_INVALID_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !id )
|
if ( id == NULL ) {
|
||||||
return RTEMS_INVALID_ADDRESS;
|
return RTEMS_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize core barrier attributes */
|
|
||||||
if ( _Attributes_Is_barrier_automatic( attribute_set ) ) {
|
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;
|
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();
|
the_barrier = _Barrier_Allocate();
|
||||||
|
|
||||||
if ( !the_barrier ) {
|
if ( the_barrier == NULL ) {
|
||||||
_Objects_Allocator_unlock();
|
_Objects_Allocator_unlock();
|
||||||
return RTEMS_TOO_MANY;
|
return RTEMS_TOO_MANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
the_barrier->attribute_set = attribute_set;
|
_CORE_barrier_Initialize( &the_barrier->Barrier, maximum_count );
|
||||||
|
|
||||||
_CORE_barrier_Initialize( &the_barrier->Barrier, &the_attributes );
|
|
||||||
|
|
||||||
*id = _Objects_Open_u32( &_Barrier_Information, &the_barrier->Object, name );
|
*id = _Objects_Open_u32( &_Barrier_Information, &the_barrier->Object, name );
|
||||||
_Objects_Allocator_unlock();
|
_Objects_Allocator_unlock();
|
||||||
|
|||||||
@@ -23,13 +23,12 @@
|
|||||||
#include <rtems/score/corebarrierimpl.h>
|
#include <rtems/score/corebarrierimpl.h>
|
||||||
|
|
||||||
void _CORE_barrier_Initialize(
|
void _CORE_barrier_Initialize(
|
||||||
CORE_barrier_Control *the_barrier,
|
CORE_barrier_Control *the_barrier,
|
||||||
CORE_barrier_Attributes *the_barrier_attributes
|
uint32_t maximum_count
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
the_barrier->Attributes = *the_barrier_attributes;
|
|
||||||
the_barrier->number_of_waiting_threads = 0;
|
the_barrier->number_of_waiting_threads = 0;
|
||||||
|
the_barrier->maximum_count = maximum_count;
|
||||||
|
|
||||||
_Thread_queue_Object_initialize( &the_barrier->Wait_queue );
|
_Thread_queue_Object_initialize( &the_barrier->Wait_queue );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,21 +61,22 @@ Status_Control _CORE_barrier_Seize(
|
|||||||
Thread_queue_Context *queue_context
|
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 );
|
_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 (
|
if ( new_number_of_waiting_threads == the_barrier->maximum_count ) {
|
||||||
_CORE_barrier_Is_automatic( &the_barrier->Attributes )
|
|
||||||
&& number_of_waiting_threads == the_barrier->Attributes.maximum_count
|
|
||||||
) {
|
|
||||||
_CORE_barrier_Surrender( the_barrier, queue_context );
|
_CORE_barrier_Surrender( the_barrier, queue_context );
|
||||||
return STATUS_BARRIER_AUTOMATICALLY_RELEASED;
|
return STATUS_BARRIER_AUTOMATICALLY_RELEASED;
|
||||||
} else {
|
} 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(
|
_Thread_queue_Context_set_thread_state(
|
||||||
queue_context,
|
queue_context,
|
||||||
STATES_WAITING_FOR_BARRIER
|
STATES_WAITING_FOR_BARRIER
|
||||||
|
|||||||
Reference in New Issue
Block a user