On Thu, Aug 19, 2021 at 11:20 AM Matt Joyce <mfjoyce2...@gmail.com> wrote: > > Added implementation of the pthread_cond_clockwait() > method to cpukit/posix/src/condclockwait.c. Additional > logic added to condwaitsupp.c to implement new method. > pthread_cond_clockwait() has been added to the Issue 8 > POSIX Standard.
"implement new" to "implement the new" > > psxcond03 test added to testsuites/psxtests to test the > newly added method. > --- > cpukit/include/rtems/posix/condimpl.h | 7 +- > cpukit/posix/src/condclockwait.c | 78 +++ > cpukit/posix/src/condtimedwait.c | 3 +- > cpukit/posix/src/condwait.c | 6 +- > cpukit/posix/src/condwaitsupp.c | 75 ++- > spec/build/testsuites/psxtests/grp.yml | 2 + > spec/build/testsuites/psxtests/psxcond03.yml | 20 + > testsuites/psxtests/Makefile.am | 9 + > testsuites/psxtests/configure.ac | 1 + > testsuites/psxtests/psxcond03/init.c | 531 ++++++++++++++++++ > testsuites/psxtests/psxcond03/psxcond03.doc | 44 ++ > testsuites/psxtests/psxcond03/psxcond03.scn | 67 +++ > testsuites/psxtests/psxcond03/system.h | 61 ++ > .../psxhdrs/pthread/pthread_cond_clockwait.c | 2 +- > 14 files changed, 875 insertions(+), 31 deletions(-) > create mode 100644 cpukit/posix/src/condclockwait.c > create mode 100644 spec/build/testsuites/psxtests/psxcond03.yml > create mode 100644 testsuites/psxtests/psxcond03/init.c > create mode 100644 testsuites/psxtests/psxcond03/psxcond03.doc > create mode 100644 testsuites/psxtests/psxcond03/psxcond03.scn > create mode 100644 testsuites/psxtests/psxcond03/system.h > > diff --git a/cpukit/include/rtems/posix/condimpl.h > b/cpukit/include/rtems/posix/condimpl.h > index 66e09bf6d8..95839e17d5 100644 > --- a/cpukit/include/rtems/posix/condimpl.h > +++ b/cpukit/include/rtems/posix/condimpl.h > @@ -150,9 +150,10 @@ int _POSIX_Condition_variables_Signal_support( > * timed wait version of condition variable wait routines. > */ > int _POSIX_Condition_variables_Wait_support( > - pthread_cond_t *cond, > - pthread_mutex_t *mutex, > - const struct timespec *abstime > + pthread_cond_t *restrict cond, > + pthread_mutex_t *restrict mutex, > + clockid_t clock_id, > + const struct timespec *restrict abstime > ); > > bool _POSIX_Condition_variables_Auto_initialization( > diff --git a/cpukit/posix/src/condclockwait.c > b/cpukit/posix/src/condclockwait.c > new file mode 100644 > index 0000000000..c2f071a749 > --- /dev/null > +++ b/cpukit/posix/src/condclockwait.c > @@ -0,0 +1,78 @@ > +/** > + * @file > + * > + * @ingroup POSIXAPI > + * > + * @brief Waiting on a Condition > + */ > + > +/* > +* Copyright (C) 2021 Matthew Joyce > +* > +* 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. > +*/ > + > +/* Defining to have access to function prototype in libc/include/pthread.h */ > +#define _GNU_SOURCE > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#include <rtems/posix/condimpl.h> > +#include <rtems/score/todimpl.h> > + > +/* > + * pthread_cond_clockwait() appears in the Issue 8 POSIX Standard > + */ > +int pthread_cond_clockwait( > + pthread_cond_t *restrict cond, > + pthread_mutex_t *restrict mutex, > + clockid_t clock_id, > + const struct timespec *restrict abstime > +) > +{ > + /* > + * POSIX Issue 8 does not specify that EINVAL is returned when abstime > + * equals NULL. > + */ > + if ( abstime == NULL ) { > + return EINVAL; > + } > + > + /* > + * POSIX Issue 8 specifies that EINVAL is returned when the clock is not > + * supported. > + */ > + if ( clock_id != CLOCK_REALTIME ) { > + if ( clock_id != CLOCK_MONOTONIC ) { > + return EINVAL; > + } > + } > + > + return _POSIX_Condition_variables_Wait_support( > + cond, > + mutex, > + clock_id, > + abstime > + ); > +} > diff --git a/cpukit/posix/src/condtimedwait.c > b/cpukit/posix/src/condtimedwait.c > index 0bc8bfc18e..9b4a9ab4a3 100644 > --- a/cpukit/posix/src/condtimedwait.c > +++ b/cpukit/posix/src/condtimedwait.c > @@ -36,8 +36,9 @@ int pthread_cond_timedwait( > return EINVAL; /* not specified */ > } > return _POSIX_Condition_variables_Wait_support( > - cond, > + cond, > mutex, > + (int)NULL, Do not cast NULL as an (int). Would be better to have a new constant in cpukit/include/rtems/posix/condimpl.h for CLOCK_NOT_SPECIFIED with a name more like the internal symbols. Set it to a value nowhere near the real clock constants, maybe something like 0xdeadbeef or whatever. Then use RTEMS_STATIC_ASSERT at the top of the waitsupp.c file to ensure your constant is not equal to ANY of the POSIX defined ones. > abstime > ); > } > diff --git a/cpukit/posix/src/condwait.c b/cpukit/posix/src/condwait.c > index 09431e216d..46e72a2579 100644 > --- a/cpukit/posix/src/condwait.c > +++ b/cpukit/posix/src/condwait.c > @@ -51,9 +51,5 @@ int pthread_cond_wait( > pthread_mutex_t *mutex > ) > { > - return _POSIX_Condition_variables_Wait_support( > - cond, > - mutex, > - NULL > - ); > + return _POSIX_Condition_variables_Wait_support(cond, mutex,(int)NULL, > NULL); Use the new constant > } > diff --git a/cpukit/posix/src/condwaitsupp.c b/cpukit/posix/src/condwaitsupp.c > index ee2f8a0787..d11d1a34d4 100644 > --- a/cpukit/posix/src/condwaitsupp.c > +++ b/cpukit/posix/src/condwaitsupp.c > @@ -92,9 +92,10 @@ static void > _POSIX_Condition_variables_Enqueue_with_timeout_realtime( > } > > int _POSIX_Condition_variables_Wait_support( > - pthread_cond_t *cond, > - pthread_mutex_t *mutex, > - const struct timespec *abstime > + pthread_cond_t *restrict cond, > + pthread_mutex_t *restrict mutex, > + clockid_t clock_id, > + const struct timespec *restrict abstime > ) > { > POSIX_Condition_variables_Control *the_cond; > @@ -107,28 +108,66 @@ int _POSIX_Condition_variables_Wait_support( > POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags ); > > _Thread_queue_Context_initialize( &queue_context ); > + > + /* > + * If there is a clock_id parameter, this is a call to > + * pthread_cond_clockwait. Set the clock according to this parameter. > + */ > + if ( clock_id ) { > + _Thread_queue_Context_set_timeout_argument( &queue_context, > + abstime, true This either does not need to wrap or needs to be formatted differently for going over 80 columns. > + ); > > - if ( abstime != NULL ) { > - _Thread_queue_Context_set_timeout_argument( &queue_context, abstime, > true ); > - > - if ( _POSIX_Condition_variables_Get_clock( flags ) == CLOCK_MONOTONIC ) { > + /* > + * We have already validated supported clocks in condclockwait.c. > + * if clock_id is not CLOCK_MONOTONIC, then it is CLOCK_REALTIME. > + */ > + if ( clock_id == CLOCK_MONOTONIC ) { > _Thread_queue_Context_set_enqueue_callout( > &queue_context, > _POSIX_Condition_variables_Enqueue_with_timeout_monotonic > ); > - } else { > - _Thread_queue_Context_set_enqueue_callout( > + } > + > + else { > + _Thread_queue_Context_set_enqueue_callout( > &queue_context, > _POSIX_Condition_variables_Enqueue_with_timeout_realtime > ); > } You might be able to clean up the code here with something like setting a local variable of this type to the callout method and then having one call to the enqueue method. that passes in the variable. Thread_queue_Enqueue_callout enqueue_callout; > - } else { > - _Thread_queue_Context_set_enqueue_callout( > - &queue_context, > - _POSIX_Condition_variables_Enqueue_no_timeout > - ); > } > > + /* > + * If there is no clock_id parameter, this is either a call to > + * cond_timedwait or cond_wait. > + */ > + else { > + > + /* If there is an abstime parameter, this is a call to cond_timedwait. */ > + if ( abstime != NULL ) { > + _Thread_queue_Context_set_timeout_argument( &queue_context, > + abstime, true > + ); > + > + if ( _POSIX_Condition_variables_Get_clock( flags ) == CLOCK_MONOTONIC > ) { > + _Thread_queue_Context_set_enqueue_callout( > + &queue_context, > + _POSIX_Condition_variables_Enqueue_with_timeout_monotonic > + ); > + } else { > + _Thread_queue_Context_set_enqueue_callout( > + &queue_context, > + _POSIX_Condition_variables_Enqueue_with_timeout_realtime > + ); > + } > + /* If there is no abstime parameter, this is a call to cond_wait. */ > + } else { > + _Thread_queue_Context_set_enqueue_callout( > + &queue_context, > + _POSIX_Condition_variables_Enqueue_no_timeout > + ); > + } > + } > executing = _POSIX_Condition_variables_Acquire( the_cond, &queue_context ); > > if ( > @@ -138,9 +177,7 @@ int _POSIX_Condition_variables_Wait_support( > _POSIX_Condition_variables_Release( the_cond, &queue_context ); > return EINVAL; > } > - > the_cond->mutex = mutex; > - > _Thread_queue_Context_set_thread_state( > &queue_context, > STATES_WAITING_FOR_CONDITION_VARIABLE > @@ -151,8 +188,8 @@ int _POSIX_Condition_variables_Wait_support( > executing, > &queue_context > ); > + > error = _POSIX_Get_error_after_wait( executing ); > - > /* > * If the thread is interrupted, while in the thread queue, by > * a POSIX signal, then pthread_cond_wait returns spuriously, > @@ -160,15 +197,12 @@ int _POSIX_Condition_variables_Wait_support( > * returns a success status, except for the fact that it was not > * woken up a pthread_cond_signal() or a pthread_cond_broadcast(). > */ > - > if ( error == EINTR ) { > error = 0; > } > - > /* > * When we get here the dispatch disable level is 0. > */ > - > if ( error != EPERM ) { > int mutex_error; > > @@ -178,6 +212,5 @@ int _POSIX_Condition_variables_Wait_support( > error = EINVAL; > } > } > - > return error; > } > diff --git a/spec/build/testsuites/psxtests/grp.yml > b/spec/build/testsuites/psxtests/grp.yml > index fb7ce465ae..dc55c05124 100644 > --- a/spec/build/testsuites/psxtests/grp.yml > +++ b/spec/build/testsuites/psxtests/grp.yml > @@ -87,6 +87,8 @@ links: > uid: psxcond01 > - role: build-dependency > uid: psxcond02 > +- role: build-dependency > + uid: psxcond03 > - role: build-dependency > uid: psxconfig01 > - role: build-dependency > diff --git a/spec/build/testsuites/psxtests/psxcond03.yml > b/spec/build/testsuites/psxtests/psxcond03.yml > new file mode 100644 > index 0000000000..c0d53eb04e > --- /dev/null > +++ b/spec/build/testsuites/psxtests/psxcond03.yml > @@ -0,0 +1,20 @@ > +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause > +build-type: test-program > +cflags: [] > +copyrights: > +- Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de) > +cppflags: [] > +cxxflags: [] > +enabled-by: true > +features: c cprogram > +includes: [] > +ldflags: [] > +links: [] > +source: > +- testsuites/psxtests/psxcond03/init.c > +- cpukit/posix/src/condclockwait.c > +stlib: [] > +target: testsuites/psxtests/psxcond03.exe > +type: build > +use-after: [] > +use-before: [] > \ No newline at end of file > diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am > index a35f00b665..de1a87b05f 100755 > --- a/testsuites/psxtests/Makefile.am > +++ b/testsuites/psxtests/Makefile.am > @@ -349,6 +349,15 @@ psxcond02_CPPFLAGS = $(AM_CPPFLAGS) > $(TEST_FLAGS_psxcond02) \ > $(support_includes) -I$(top_srcdir)/include > endif > > +if TEST_psxcond03 > +psx_tests += psxcond03 > +psx_screens += psxcond03/psxcond03.scn > +psx_docs += psxcond03/psxcond03.doc > +psxcond03_SOURCES = psxcond03/init.c psxcond03/system.h include/pmacros.h > +psxcond03_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_psxcond03) \ > + $(support_includes) -I$(top_srcdir)/include > +endif > + > if TEST_psxconfig01 > psx_tests += psxconfig01 > psx_screens += psxconfig01/psxconfig01.scn > diff --git a/testsuites/psxtests/configure.ac > b/testsuites/psxtests/configure.ac > index 3f95010cd3..d88f52a846 100644 > --- a/testsuites/psxtests/configure.ac > +++ b/testsuites/psxtests/configure.ac > @@ -79,6 +79,7 @@ RTEMS_TEST_CHECK([psxclockrealtime01]) > RTEMS_TEST_CHECK([psxconcurrency01]) > RTEMS_TEST_CHECK([psxcond01]) > RTEMS_TEST_CHECK([psxcond02]) > +RTEMS_TEST_CHECK([psxcond03]) > RTEMS_TEST_CHECK([psxconfig01]) > RTEMS_TEST_CHECK([psxdevctl01]) > RTEMS_TEST_CHECK([psxeintr_join]) > diff --git a/testsuites/psxtests/psxcond03/init.c > b/testsuites/psxtests/psxcond03/init.c > new file mode 100644 > index 0000000000..bb1daf1b8b > --- /dev/null > +++ b/testsuites/psxtests/psxcond03/init.c > @@ -0,0 +1,531 @@ > +/* > +* Copyright (C) 2021 Matthew Joyce > +* > +* 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. > +*/ > + > +/* Defining in order to access pthread_cond_clockwait in pthread.h */ > +#define _GNU_SOURCE > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#define CONFIGURE_INIT > +#include <pthread.h> > +#include <sched.h> > +#include <errno.h> > +#include <rtems.h> > +#include <tmacros.h> > +#include "system.h" > + > +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; > +pthread_cond_t bad_cond; > +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; > +pthread_mutex_t bad_mutex; > +pthread_mutex_t new_mutex = PTHREAD_MUTEX_INITIALIZER; > +clockid_t clock_id1 = CLOCK_MONOTONIC; > +clockid_t clock_id2 = CLOCK_REALTIME; > +clockid_t clock_id3 = CLOCK_MONOTONIC_RAW; > +int count; > +int eno; > +int status; > +const char rtems_test_name[] = "PSXCOND 3"; > + > +void *POSIX_Init( > + void *argument > +) > +{ > + TEST_BEGIN(); > + empty_line(); > + pthread_t t1; > + struct timespec abstime; > + > + /* Expected pass: Clock Monotonic with sufficient abstime */ > + printf("1st iteration Begin (Clock Monotonic)\n"); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "1st iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Clock Monotonic with insufficient abstime */ > + printf( "2nd iteration Begin (Clock Monotonic)\n" ); > + abstime.tv_sec = 0; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == ETIMEDOUT ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "2nd iteration END\n" ); > + empty_line(); > + > + /* Expected pass: Clock Realtime with sufficient abstime */ > + printf( "3rd iteration Begin (Clock Realtime)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec += 4; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "3rd iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Clock Realtime with insufficient abstime */ > + printf( "4th iteration Begin (Clock Realtime)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec = 0; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == ETIMEDOUT ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "4th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Unsupported Clock */ > + printf( "5th iteration Begin (Unsupported Clock)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id3, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == EINVAL ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "5th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Invalid Clock */ > + printf( "6th iteration Begin (Invalid Clock)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, (int)NULL, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == EINVAL ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "6th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Invalid Clock */ > + printf( "7th iteration Begin (Invalid Abstime)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &mutex, clock_id1, NULL ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == EINVAL ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "7th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Invalid Clock */ > + printf( "8th iteration Begin (Invalid Cond)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( NULL, &mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == EINVAL ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "8th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Invalid Mutex */ > + printf( "9th iteration Begin (Invalid Mutex)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, NULL, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno != 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "9th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Uninitialized condition variable */ > + printf( "10th iteration Begin (Uninitialized Condition Variable)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &bad_cond, &mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno != 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "10th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Uninitialized condition variable */ > + printf( "11th iteration Begin (Uninitialized Mutex)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &bad_mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno != 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "11th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Uninitialized condition variable */ > + printf( "12th iteration Begin (Uninitialized Condition Variable)\n" ); > + abstime.tv_sec = 2; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &bad_cond, &mutex, clock_id1, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno != 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "12th iteration END\n" ); > + empty_line(); > + > + /* Expected pass: Binding new mutex to condition variable */ > + printf( "13th iteration Begin (New Mutex)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec += 4; > + abstime.tv_nsec = 1; > + status = pthread_create( &t1, NULL, thread_func2, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &new_mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "13th iteration END\n" ); > + empty_line(); > + > + /* Expected fail: Timeout (abstime < current time) */ > + printf( "14th iteration Begin (abstime < current time)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec -= 1; > + abstime.tv_nsec -= 1; > + status = pthread_create( &t1, NULL, thread_func2, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &new_mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == ETIMEDOUT ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "14th iteration END\n" ); > + empty_line(); > + > + /* Expected Pass: Sufficient abstime to exceed sleep in thread_func3*/ > + printf( "15th iteration Begin (sufficient abstime to exceed sleep)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec += 4; > + abstime.tv_nsec += 1; > + status = pthread_create( &t1, NULL, thread_func3, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &new_mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == 0 ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "15th iteration END\n" ); > + empty_line(); > + > + /* Expected Fail: Insufficient abstime to exceed sleep in thread_func3*/ > + printf( "16th iteration Begin (insufficient abstime to exceed sleep)\n" ); > + status = clock_gettime( clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + abstime.tv_sec += 2; > + abstime.tv_nsec += 1; > + status = pthread_create( &t1, NULL, thread_func3, NULL ); > + rtems_test_assert( status == 0 ); > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + while ( count == 0 ){ > + eno = pthread_cond_clockwait( &cond, &new_mutex, clock_id2, &abstime ); > + if ( eno != 0 ) { > + break; > + } > + } > + > + count -= 1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( eno == ETIMEDOUT ); > + printf( "Return value from cond_clockwait is %d\n", eno ); > + status = pthread_join( t1, NULL ); > + rtems_test_assert( status == 0 ); > + printf( "16th iteration END\n" ); > + empty_line(); > + > + TEST_END(); > + rtems_test_exit( 0 ); > + return NULL; > +} > + > +void *thread_func( void *arg ) > +{ > + int status; > + > + status = pthread_mutex_lock( &mutex ); > + rtems_test_assert( status == 0 ); > + if (count == 0) { > + status = pthread_cond_signal( &cond ); > + rtems_test_assert( status == 0 ); > + } > + > + count +=1; > + status = pthread_mutex_unlock( &mutex ); > + rtems_test_assert( status == 0 ); > + return NULL; > +} > + > +void *thread_func2( void *arg ) > +{ > + int status; > + > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + if ( count == 0 ) { > + status = pthread_cond_signal( &cond ); > + rtems_test_assert( status == 0 ); > + } > + > + count +=1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + return NULL; > +} > + > +void *thread_func3( void *arg ) > +{ > + int status; > + > + status = pthread_mutex_lock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + /* Arbitrary sleep to test timeout functionality */ > + sleep(3); > + if ( count == 0 ) { > + status = pthread_cond_signal( &cond ); > + rtems_test_assert( status == 0 ); > + } > + > + count +=1; > + status = pthread_mutex_unlock( &new_mutex ); > + rtems_test_assert( status == 0 ); > + return NULL; > +} Still a lot of printing. Is comparing the screen needed to know it passed? You should either delete the printfs of put them inside a debug macro and turn them off by default. > diff --git a/testsuites/psxtests/psxcond03/psxcond03.doc > b/testsuites/psxtests/psxcond03/psxcond03.doc > new file mode 100644 > index 0000000000..4e9b582189 > --- /dev/null > +++ b/testsuites/psxtests/psxcond03/psxcond03.doc > @@ -0,0 +1,44 @@ > +/* > +* Copyright (C) 2021 Matthew Joyce > +* > +* 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. > +*/ > + > +This file describes the directives and concepts tested by this test set. > + > +test set name: psxcond03 > + > +directives: > + > + pthread_cond_clockwait > + pthread_create > + pthread_mutex_lock > + pthread_mutex_unlock > + pthread_cond_signal > + pthread_join > + > +concepts: > + > ++ Tests the newly-added Issue 8 POSIX Standard pthread_cond_clockwait method. > + Tests include valid/supported and invalid/unsupported clocks, sufficient > and > + insufficient timeouts, and invalid or uninitialized condition/mutex > + parameters. > diff --git a/testsuites/psxtests/psxcond03/psxcond03.scn > b/testsuites/psxtests/psxcond03/psxcond03.scn > new file mode 100644 > index 0000000000..e1792ca9cd > --- /dev/null > +++ b/testsuites/psxtests/psxcond03/psxcond03.scn > @@ -0,0 +1,67 @@ > +*** BEGIN OF TEST PSXCOND 3 *** > + > +1st iteration Begin (Clock Monotonic) > +Return value from cond_clockwait is 0 > +1st iteration END > + > +2nd iteration Begin (Clock Monotonic) > +Return value from cond_clockwait is 116 > +2nd iteration END > + > +3rd iteration Begin (Clock Realtime) > +Return value from cond_clockwait is 0 > +3rd iteration END > + > +4th iteration Begin (Clock Realtime) > +Return value from cond_clockwait is 116 > +4th iteration END > + > +5th iteration Begin (Unsupported Clock) > +Return value from cond_clockwait is 22 > +5th iteration END > + > +6th iteration Begin (Invalid Clock) > +Return value from cond_clockwait is 22 > +6th iteration END > + > +7th iteration Begin (Invalid Abstime) > +Return value from cond_clockwait is 22 > +7th iteration END > + > +8th iteration Begin (Invalid Cond) > +Return value from cond_clockwait is 22 > +8th iteration END > + > +9th iteration Begin (Invalid Mutex) > +Return value from cond_clockwait is 1 > +9th iteration END > + > +10th iteration Begin (Uninitialized Condition Variable) > +Return value from cond_clockwait is 116 > +10th iteration END > + > +11th iteration Begin (Uninitialized Mutex) > +Return value from cond_clockwait is 116 > +11th iteration END > + > +12th iteration Begin (Uninitialized Condition Variable) > +Return value from cond_clockwait is 116 > +12th iteration END > + > +13th iteration Begin (New Mutex) > +Return value from cond_clockwait is 0 > +13th iteration END > + > +14th iteration Begin (abstime < current time) > +Return value from cond_clockwait is 116 > +14th iteration END > + > +15th iteration Begin (sufficient abstime to exceed sleep) > +Return value from cond_clockwait is 0 > +15th iteration END > + > +16th iteration Begin (insufficient abstime to exceed sleep) > +Return value from cond_clockwait is 116 > +16th iteration END > + > +*** END OF TEST PSXCOND 3 *** > diff --git a/testsuites/psxtests/psxcond03/system.h > b/testsuites/psxtests/psxcond03/system.h > new file mode 100644 > index 0000000000..b9dcb832ad > --- /dev/null > +++ b/testsuites/psxtests/psxcond03/system.h > @@ -0,0 +1,61 @@ > +/* > +* Copyright (C) 2021 Matthew Joyce > +* > +* 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. > +*/ > + > +/* functions */ > + > +#include <pmacros.h> > +#include <unistd.h> > +#include <errno.h> > + > +void *POSIX_Init( > + void *argument > +); > + > +void *thread_func( > + void *argument > +); > + > +void *thread_func2( > + void *argument > +); > + > +void *thread_func3( > + void *argument > +); > + > +/* configuration information */ > + > +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER > + > +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION > + > +#define CONFIGURE_MAXIMUM_POSIX_THREADS 4 > + > +#define CONFIGURE_POSIX_INIT_THREAD_TABLE > + > +#include <rtems/confdefs.h> > + > +/* end of include file */ > diff --git a/testsuites/psxtests/psxhdrs/pthread/pthread_cond_clockwait.c > b/testsuites/psxtests/psxhdrs/pthread/pthread_cond_clockwait.c > index 15485eb587..fe91b7954f 100644 > --- a/testsuites/psxtests/psxhdrs/pthread/pthread_cond_clockwait.c > +++ b/testsuites/psxtests/psxhdrs/pthread/pthread_cond_clockwait.c > @@ -49,7 +49,7 @@ int test( void ) > pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; > clockid_t clock_id = CLOCK_REALTIME; > struct timespec abstime; > - abstime.tv_sec = 2; > + abstime.tv_sec = 1; > int result; > > /* This method appeared in the Issue 8 POSIX Standard */ > -- > 2.31.1 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel