[PATCH 1/1] Added Implementation / tests for pthread_cond_clockwait()
Matt Joyce
mfjoyce2004 at gmail.com
Sat Sep 18 14:46:30 UTC 2021
Added implementation of the pthread_cond_clockwait()
method to cpukit/posix/src/condclockwait.c. Additional
logic added to condwaitsupp.c to implement the new
method. Pthread_cond_clockwait() has been added to the
Issue 8 POSIX Standard.
psxcond03 test added to testsuites/psxtests to test the
newly added method.
---
cpukit/include/rtems/posix/condimpl.h | 9 +-
cpukit/posix/src/condclockwait.c | 78 +++
cpukit/posix/src/condtimedwait.c | 3 +-
cpukit/posix/src/condwait.c | 1 +
cpukit/posix/src/condwaitsupp.c | 114 ++++-
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 | 466 ++++++++++++++++++
testsuites/psxtests/psxcond03/psxcond03.doc | 44 ++
testsuites/psxtests/psxcond03/psxcond03.scn | 3 +
testsuites/psxtests/psxcond03/system.h | 61 +++
.../psxhdrs/pthread/pthread_cond_clockwait.c | 2 +-
14 files changed, 788 insertions(+), 25 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..c49fbb24d4 100644
--- a/cpukit/include/rtems/posix/condimpl.h
+++ b/cpukit/include/rtems/posix/condimpl.h
@@ -39,6 +39,8 @@ typedef struct {
#define POSIX_CONDITION_VARIABLES_MAGIC 0x18dfb1feUL
+#define CLOCK_NOT_SPECIFIED 0xdeadbeef
+
/**
* Constant to indicate condition variable does not currently have
* a mutex assigned to it.
@@ -150,9 +152,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..ebc95c86b4
--- /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..cefd1d6cb6 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,
+ CLOCK_NOT_SPECIFIED,
abstime
);
}
diff --git a/cpukit/posix/src/condwait.c b/cpukit/posix/src/condwait.c
index 09431e216d..85ca8e27c7 100644
--- a/cpukit/posix/src/condwait.c
+++ b/cpukit/posix/src/condwait.c
@@ -54,6 +54,7 @@ int pthread_cond_wait(
return _POSIX_Condition_variables_Wait_support(
cond,
mutex,
+ CLOCK_NOT_SPECIFIED,
NULL
);
}
diff --git a/cpukit/posix/src/condwaitsupp.c b/cpukit/posix/src/condwaitsupp.c
index ee2f8a0787..01d5ca9794 100644
--- a/cpukit/posix/src/condwaitsupp.c
+++ b/cpukit/posix/src/condwaitsupp.c
@@ -26,6 +26,57 @@
#include <rtems/score/status.h>
#include <rtems/score/threaddispatch.h>
+#ifdef CLOCK_REALTIME_COARSE
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_REALTIME_COARSE),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_PROCESS_CPUTIME_ID),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_REALTIME
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_REALTIME),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_THREAD_CPUTIME_ID),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_MONOTONIC
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_MONOTONIC),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_MONOTONIC_RAW),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_MONOTONIC_COARSE
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_MONOTONIC_COARSE),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_BOOTTIME
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_BOOTTIME),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_REALTIME_ALARM
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_REALTIME_ALARM),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+#ifdef CLOCK_BOOTTIME_ALARM
+ RTEMS_STATIC_ASSERT(
+ ( CLOCK_NOT_SPECIFIED != CLOCK_BOOTTIME_ALARM),
+ "CLOCK_NOT_SPECIFIED conflicts with existing POSIX defined clock/n" );
+#endif
+
static void _POSIX_Condition_variables_Mutex_unlock(
Thread_queue_Queue *queue,
Thread_Control *the_thread,
@@ -92,37 +143,66 @@ 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;
- unsigned long flags;
- Thread_queue_Context queue_context;
- int error;
+ unsigned long flags;
+ Thread_queue_Context queue_context;
+ int error;
Thread_Control *executing;
+ pthread_condattr_t attr;
the_cond = _POSIX_Condition_variables_Get( cond );
POSIX_CONDITION_VARIABLES_VALIDATE_OBJECT( the_cond, flags );
_Thread_queue_Context_initialize( &queue_context );
- if ( abstime != NULL ) {
- _Thread_queue_Context_set_timeout_argument( &queue_context, abstime, true );
+ _Thread_queue_Context_set_timeout_argument( &queue_context, abstime, true );
+
+ error = pthread_condattr_init( &attr );
+ _Assert( error == 0 );
- if ( _POSIX_Condition_variables_Get_clock( flags ) == CLOCK_MONOTONIC ) {
+ /*
+ * If the parameter clock_id is not specified, then the clock from the
+ * condition attributes shall be used.
+ */
+ if ( clock_id == CLOCK_NOT_SPECIFIED ) {
+ error = pthread_condattr_getclock( &attr, &clock_id );
+ _Assert( error == 0 );
+ }
+
+ /*
+ * Now we have the desired clock_id, whether it came from cond_timedwait or
+ * cond_clockwait. If abstime is specified, we use the clock_id to set the
+ * correct timeout.
+ */
+ if ( abstime != NULL ) {
+ /*
+ * 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(
+ _Thread_queue_Context_set_enqueue_callout(
&queue_context,
_POSIX_Condition_variables_Enqueue_with_timeout_realtime
- );
- }
- } else {
+ );
+ }
+ }
+
+ /*
+ * Otherwise, if the abstime parameter is NULL, this is a call to
+ * pthread_cond_wait and no timeout is necessary.
+ */
+ else {
_Thread_queue_Context_set_enqueue_callout(
&queue_context,
_POSIX_Condition_variables_Enqueue_no_timeout
@@ -138,9 +218,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 +229,8 @@ int _POSIX_Condition_variables_Wait_support(
executing,
&queue_context
);
- error = _POSIX_Get_error_after_wait( executing );
+ 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 +238,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 +253,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..54d5d5c7a4
--- /dev/null
+++ b/testsuites/psxtests/psxcond03/init.c
@@ -0,0 +1,466 @@
+/*
+* 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();
+ pthread_t t1;
+ struct timespec abstime;
+
+ /* Expected pass: Clock Monotonic with sufficient abstime */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Clock Monotonic with insufficient abstime */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected pass: Clock Realtime with sufficient abstime */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Clock Realtime with insufficient abstime */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Unsupported Clock */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Invalid Clock */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Invalid Clock */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Invalid Clock */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Invalid Mutex */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Uninitialized condition variable */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Uninitialized condition variable */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Uninitialized condition variable */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected pass: Binding new mutex to condition variable */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected fail: Timeout (abstime < current time) */
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected Pass: Sufficient abstime to exceed sleep in thread_func3*/
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ /* Expected Fail: Insufficient abstime to exceed sleep in thread_func3*/
+ 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 );
+ status = pthread_join( t1, NULL );
+ rtems_test_assert( status == 0 );
+
+ 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;
+}
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..5935b1d478
--- /dev/null
+++ b/testsuites/psxtests/psxcond03/psxcond03.scn
@@ -0,0 +1,3 @@
+*** BEGIN OF TEST PSXCOND 3 ***
+
+*** 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
More information about the devel
mailing list