[PATCH 1/1] v2: Implement Condclockwait and Test

Matt Joyce mfjoyce2004 at gmail.com
Thu Aug 19 16:20:23 UTC 2021


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.

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,
     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);
 }
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 
+    );
 
-  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
       );
     }
-  } 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; 
+}
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



More information about the devel mailing list