diff --git a/cpukit/include/rtems/rtems/barrier.h b/cpukit/include/rtems/rtems/barrier.h index 029cffb406..f8ccf4113b 100644 --- a/cpukit/include/rtems/rtems/barrier.h +++ b/cpukit/include/rtems/rtems/barrier.h @@ -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 diff --git a/cpukit/include/rtems/score/corebarrierimpl.h b/cpukit/include/rtems/score/corebarrierimpl.h index b58bc44b4c..3e2803b2d7 100644 --- a/cpukit/include/rtems/score/corebarrierimpl.h +++ b/cpukit/include/rtems/score/corebarrierimpl.h @@ -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 diff --git a/cpukit/rtems/src/barriergetnumwaiting.c b/cpukit/rtems/src/barriergetnumwaiting.c new file mode 100644 index 0000000000..a6aba5b569 --- /dev/null +++ b/cpukit/rtems/src/barriergetnumwaiting.c @@ -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_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; +} diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml index 5feda1267a..1752fba772 100644 --- a/spec/build/cpukit/librtemscpu.yml +++ b/spec/build/cpukit/librtemscpu.yml @@ -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 diff --git a/testsuites/sptests/sp33/init.c b/testsuites/sptests/sp33/init.c index c6fb8c5714..27374a66e8 100644 --- a/testsuites/sptests/sp33/init.c +++ b/testsuites/sptests/sp33/init.c @@ -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; diff --git a/testsuites/sptests/sp33/sp33.doc b/testsuites/sptests/sp33/sp33.doc index a7d3fb304a..dcf8422847 100644 --- a/testsuites/sptests/sp33/sp33.doc +++ b/testsuites/sptests/sp33/sp33.doc @@ -36,6 +36,7 @@ directives: status = rtems_barrier_ident status = rtems_barrier_wait status = rtems_barrier_release + status = rtems_barrier_get_number_waiting concepts: diff --git a/testsuites/sptests/sp33/sp33.scn b/testsuites/sptests/sp33/sp33.scn index 577f226e56..562ef47705 100644 --- a/testsuites/sptests/sp33/sp33.scn +++ b/testsuites/sptests/sp33/sp33.scn @@ -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 *** +