cpukit/rtems: add rtems_barrier_get_number_waiting()

Closes rtems/programs/gsoc#9
Added rtems_get_number_waiting according to the issue
rtems/programs/gsoc#9, including tests and documentation.
This commit is contained in:
mez3n
2025-03-21 00:08:29 +02:00
committed by Joel Sherrill
parent 0017330fc6
commit 528095cd24
7 changed files with 193 additions and 1 deletions

View File

@@ -349,6 +349,43 @@ rtems_status_code rtems_barrier_wait( rtems_id id, rtems_interval timeout );
*/
rtems_status_code rtems_barrier_release( rtems_id id, uint32_t *released );
/* Generated from spec:/rtems/barrier/if/get-number-waiting */
/**
* @ingroup RTEMSAPIClassicBarrier
*
* @brief Gets the number of tasks waiting at the barrier.
*
* @param id is the barrier identifier.
*
* @param[out] waiting is the pointer to an uint32_t object. When the directive
* call is successful, the number of waiting tasks will be stored in this
* object.
*
* This directive gets the number of tasks waiting at the barrier specified by
* ``id``. The number of waiting tasks will be returned in ``waiting``.
*
* @retval ::RTEMS_SUCCESSFUL The requested operation was successful.
*
* @retval ::RTEMS_INVALID_ADDRESS The ``waiting`` parameter was NULL.
*
* @retval ::RTEMS_INVALID_ID There was no barrier associated with the
* identifier specified by ``id``.
*
* @par Constraints
* @parblock
* The following constraints apply to this directive:
*
* * The directive may be called from within interrupt context.
*
* * The directive may be called from within task context.
* @endparblock
*/
rtems_status_code rtems_barrier_get_number_waiting(
rtems_id id,
uint32_t *waiting
);
#ifdef __cplusplus
}
#endif

View File

@@ -189,6 +189,23 @@ static inline void _CORE_barrier_Flush(
);
}
/**
* @brief Gets the number of threads waiting at the barrier.
*
* This routine returns the count of threads currently waiting at the barrier.
*
* @param[in] the_barrier The barrier to check.
* @param[in] queue_context The thread queue context.
*
* @return The number of threads currently waiting at the barrier.
*/
static inline uint32_t _CORE_barrier_Get_number_waiting(
const CORE_barrier_Control *the_barrier
)
{
return the_barrier->number_of_waiting_threads;
}
/** @} */
#ifdef __cplusplus

View File

@@ -0,0 +1,68 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/**
* @file
*
* @ingroup RTEMSImplClassicBarrier
*
* @brief This source file contains the implementation of
* rtems_barrier_get_number_waiting().
*/
/*
* Copyright (C) 2025 Mazen Adel Elmessady
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/rtems/barrierimpl.h>
rtems_status_code rtems_barrier_get_number_waiting(
rtems_id id,
uint32_t *waiting
)
{
Barrier_Control *the_barrier;
Thread_queue_Context queue_context;
if ( waiting == NULL ) {
return RTEMS_INVALID_ADDRESS;
}
the_barrier = _Barrier_Get( id, &queue_context );
if ( the_barrier == NULL ) {
return RTEMS_INVALID_ID;
}
_CORE_barrier_Acquire_critical( &the_barrier->Barrier, &queue_context );
*waiting = _CORE_barrier_Get_number_waiting( &the_barrier->Barrier );
_CORE_barrier_Release( &the_barrier->Barrier, &queue_context );
return RTEMS_SUCCESSFUL;
}

View File

@@ -1206,6 +1206,7 @@ source:
- cpukit/rtems/src/barrierdelete.c
- cpukit/rtems/src/barrierident.c
- cpukit/rtems/src/barrierrelease.c
- cpukit/rtems/src/barriergetnumwaiting.c
- cpukit/rtems/src/barrierwait.c
- cpukit/rtems/src/clockgetsecondssinceepoch.c
- cpukit/rtems/src/clockgettickssinceboot.c

View File

@@ -91,6 +91,7 @@ rtems_task Init(
rtems_status_code status;
rtems_name name = rtems_build_name('B','A','R','1');
uint32_t released;
uint32_t waiting;
rtems_id testId;
rtems_id Tasks[CONFIGURE_MAXIMUM_TASKS-1];
uint32_t i;
@@ -114,6 +115,14 @@ rtems_task Init(
"rtems_barrier_release did not return RTEMS_INVALID_ID"
);
puts( "rtems_barrier_get_number_waiting - bad id - INVALID_ID" );
status = rtems_barrier_get_number_waiting( 100, &waiting );
fatal_directive_status(
status,
RTEMS_INVALID_ID,
"rtems_barrier_get_number_waiting did not return RTEMS_INVALID_ID"
);
puts( "rtems_barrier_wait - bad id - INVALID_ID" );
status = rtems_barrier_wait( 100, 10 );
fatal_directive_status(
@@ -202,6 +211,28 @@ rtems_task Init(
rtems_test_exit(0);
}
/* Get number waiting with bad return pointer */
puts(
"rtems_barrier_get_number_waiting - NULL return count - INVALID_ADDRESS"
);
status = rtems_barrier_get_number_waiting( Barrier, NULL );
fatal_directive_status(
status,
RTEMS_INVALID_ADDRESS,
"rtems_barrier_get_number_waiting bad return pointer"
);
/* number of waiting tasks must be 0 */
status = rtems_barrier_get_number_waiting( Barrier, &waiting );
directive_failed(status, "rtems_barrier_get_number_waiting");
if ( waiting != 0 ) {
printf(
"ERROR -- rtems_barrier_get_number_waiting -- waiting != 0, = %" PRIu32,
waiting
);
rtems_test_exit(0);
}
/* Create some tasks to wait for the barrier */
SuccessfulCase = TRUE;
DeletedCase = FALSE;
@@ -225,6 +256,20 @@ rtems_task Init(
status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
directive_failed(status, "rtems_task_wake_after");
/* Gets the number of tasks that are waiting at the barrier */
puts( "Getting the number of tasks that are waiting at the barrier" );
status = rtems_barrier_get_number_waiting( Barrier, &waiting );
printf("Number of tasks waiting at the barrier: %" PRIu32 "\n", waiting);
directive_failed(status, "rtems_barrier_get_number_waiting" );
if ( waiting != ( CONFIGURE_MAXIMUM_TASKS - 1 ) ) {
printf(
"ERROR -- rtems_barrier_get_number_waiting -- waiting != %d, = %" PRIu32,
( CONFIGURE_MAXIMUM_TASKS - 1 ),
waiting
);
rtems_test_exit(0);
}
/* Release tasks which were waiting */
puts( "Releasing tasks" );
status = rtems_barrier_release( Barrier, &released );
@@ -242,6 +287,21 @@ rtems_task Init(
status = rtems_task_wake_after( rtems_clock_get_ticks_per_second() );
directive_failed(status, "rtems_task_wake_after");
/* Gets the number of tasks that are waiting at the barrier */
puts( "Getting the number of tasks that are waiting at the barrier" );
status = rtems_barrier_get_number_waiting( Barrier, &waiting );
printf("Number of tasks waiting at the barrier: %" PRIu32 "\n", waiting);
directive_failed(status, "rtems_barrier_get_number_waiting" );
if ( waiting != 0 ) {
printf(
"ERROR -- rtems_barrier_get_number_waiting -- waiting != %d, = %" PRIu32,
0,
waiting
);
rtems_test_exit(0);
}
/* Create some tasks to wait for the barrier */
SuccessfulCase = FALSE;
DeletedCase = TRUE;

View File

@@ -36,6 +36,7 @@ directives:
status = rtems_barrier_ident
status = rtems_barrier_wait
status = rtems_barrier_release
status = rtems_barrier_get_number_waiting
concepts:

View File

@@ -1,6 +1,7 @@
*** TEST 33 ***
rtems_barrier_delete - bad id - INVALID_ID
rtems_barrier_release - bad id - INVALID_ID
rtems_barrier_get_number_waiting - bad id - INVALID_ID
rtems_barrier_wait - bad id - INVALID_ID
Create barrier with automatic release and 0 max waiters
rtems_barrier_create - bad name - INVALID_NAME
@@ -10,6 +11,7 @@ rtems_barrier_create - too many
Check barrier ident
Wait on barrier w/timeout and TIMEOUT
rtems_barrier_release - NULL return count - INVALID_ADDRESS
rtems_barrier_get_number_waiting - NULL return count - INVALID_ADDRESS
*** Testing manual release of barrier ***
Delay to let Waiters block
@@ -17,12 +19,16 @@ Waiter 0 waiting on barrier
Waiter 1 waiting on barrier
Waiter 2 waiting on barrier
Waiter 3 waiting on barrier
Getting the number of tasks that are waiting at the barrier
Number of tasks waiting at the barrier: 4
Releasing tasks
Delay to let Waiters print a message
Waiter 0 back from barrier
Waiter 1 back from barrier
Waiter 2 back from barrier
Waiter 3 back from barrier
Getting the number of tasks that are waiting at the barrier
Number of tasks waiting at the barrier: 0
*** Testing Deletion of barrier ***
Delay to let Waiters block
@@ -48,4 +54,6 @@ Waiter 3 back from barrier
Waiter 0 back from barrier
Waiter 1 back from barrier
Waiter 2 back from barrier
*** END OF TEST 33 ***
*** END OF TEST SP 33 ***