On Fri, Oct 8, 2021 at 8:23 AM Matt Joyce <mfjoyce2...@gmail.com> wrote: > > Added implementations of the pthread_rwlock_clockrdlock and > the pthread_rwlock_clockwrlock methods to cpukit/posix/src. Both of these > methods have been newly added to the POSIX Issue 8 Standard. > > psxrwlock02 test added to testsuites/psxtests to test the newly added > methods. > --- > cpukit/posix/src/prwlockclockrdlock.c | 70 ++ > cpukit/posix/src/prwlockclockwrlock.c | 71 ++ > spec/build/testsuites/psxtests/grp.yml | 2 + > .../build/testsuites/psxtests/psxrwlock02.yml | 22 + > testsuites/psxtests/Makefile.am | 9 + > testsuites/psxtests/configure.ac | 1 + > testsuites/psxtests/psxrwlock02/main.c | 55 ++ > testsuites/psxtests/psxrwlock02/test.c | 750 ++++++++++++++++++ > 8 files changed, 980 insertions(+) > create mode 100644 cpukit/posix/src/prwlockclockrdlock.c > create mode 100644 cpukit/posix/src/prwlockclockwrlock.c > create mode 100644 spec/build/testsuites/psxtests/psxrwlock02.yml > create mode 100644 testsuites/psxtests/psxrwlock02/main.c > create mode 100644 testsuites/psxtests/psxrwlock02/test.c > > diff --git a/cpukit/posix/src/prwlockclockrdlock.c > b/cpukit/posix/src/prwlockclockrdlock.c > new file mode 100644 > index 0000000000..d7187ebfb7 > --- /dev/null > +++ b/cpukit/posix/src/prwlockclockrdlock.c > @@ -0,0 +1,70 @@ > +/** > + * @file > + * > + * @ingroup POSIXAPI > + * > + * @brief Attempt to Obtain a Read Lock on a RWLock Instance > + */ > + > +/* > + * POSIX RWLock Manager -- Attempt to Obtain a Read Lock on a RWLock > Instance. > + * The timeout is specified by abstime on the clock specified by clock_id. > + * > + * COPYRIGHT (c) 2021 Matthew Joyce > + * COPYRIGHT (c) 1989-2008. > + * On-Line Applications Research Corporation (OAR). > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */
Since this is new, feel free to convert the license to BSD-2-Clause and add SPDX annotation. Plenty of examples for this. > + > +/* 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/rwlockimpl.h> > +#include <rtems/posix/posixapi.h> > + > +/* The POSIX Issue 8 Standard adds pthread_rwlock_clockrdlock */ > +int pthread_rwlock_clockrdlock( > + pthread_rwlock_t *rwlock, > + clockid_t clock_id, > + const struct timespec *abstime These don't look lined up. > +) > +{ > + POSIX_RWLock_Control *the_rwlock; > + Thread_queue_Context queue_context; > + Status_Control status; Lined up again? > + > + the_rwlock = _POSIX_RWLock_Get( rwlock ); > + POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock ); > + > + _Thread_queue_Context_initialize( &queue_context ); > + > + if ( clock_id == CLOCK_REALTIME ) { > + _Thread_queue_Context_set_enqueue_timeout_realtime_timespec( > + &queue_context, > + abstime, > + true > + ); > + } Should there be an else here? What if it is another CLOCK_ABC value? Shouldn't that be an error? > + if ( clock_id == CLOCK_MONOTONIC ) { > + _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec( > + &queue_context, > + abstime, > + true > + ); > + } > + > + status = _CORE_RWLock_Seize_for_reading( > + &the_rwlock->RWLock, > + true, > + &queue_context > + ); > + return _POSIX_Get_error( status ); > +} > diff --git a/cpukit/posix/src/prwlockclockwrlock.c > b/cpukit/posix/src/prwlockclockwrlock.c > new file mode 100644 > index 0000000000..c0ed7fe01c > --- /dev/null > +++ b/cpukit/posix/src/prwlockclockwrlock.c > @@ -0,0 +1,71 @@ > +/** > + * @file > + * > + * @ingroup POSIXAPI > + * > + * @brief Attempt to Obtain a Write lock on a RWLock instance > + */ > + > +/* > + * POSIX RWLock Manager -- Attempt to Obtain a Write Lock on a RWLock > Instance > + * The timeout is specified by abstime on the clock specified by clock_id. > + * > + * COPYRIGHT (c) 2021 Matthew Joyce > + * COPYRIGHT (c) 1989-2008. > + * On-Line Applications Research Corporation (OAR). > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ BSD-2 again > + > +/* 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/rwlockimpl.h> > +#include <rtems/posix/posixapi.h> > + > + > +/* The POSIX Issue 8 Standard adds pthread_rwlock_clockwrlock */ > +int pthread_rwlock_clockwrlock( > + pthread_rwlock_t *rwlock, > + clockid_t clock_id, > + const struct timespec *abstime Alignment > +) > +{ > + POSIX_RWLock_Control *the_rwlock; > + Thread_queue_Context queue_context; > + Status_Control status; Alignment > + > + the_rwlock = _POSIX_RWLock_Get( rwlock ); > + POSIX_RWLOCK_VALIDATE_OBJECT( the_rwlock ); > + > + _Thread_queue_Context_initialize( &queue_context ); > + > + if ( clock_id == CLOCK_REALTIME ) { > + _Thread_queue_Context_set_enqueue_timeout_realtime_timespec( > + &queue_context, > + abstime, > + true > + ); > + } Same issue on else and error checking other clock values. There is likely a need to exit a critical section on clock type error. > + > + if ( clock_id == CLOCK_MONOTONIC ) { > + _Thread_queue_Context_set_enqueue_timeout_monotonic_timespec( > + &queue_context, > + abstime, > + true > + ); > + } > + > + status = _CORE_RWLock_Seize_for_writing( > + &the_rwlock->RWLock, > + true, > + &queue_context > + ); > + return _POSIX_Get_error( status ); > +} > diff --git a/spec/build/testsuites/psxtests/grp.yml > b/spec/build/testsuites/psxtests/grp.yml > index fb7ce465ae..51b8d1d758 100644 > --- a/spec/build/testsuites/psxtests/grp.yml > +++ b/spec/build/testsuites/psxtests/grp.yml > @@ -183,6 +183,8 @@ links: > uid: psxreaddir > - role: build-dependency > uid: psxrwlock01 > +- role: build-dependency > + uid: psxrwlock02 > - role: build-dependency > uid: psxsem01 > - role: build-dependency > diff --git a/spec/build/testsuites/psxtests/psxrwlock02.yml > b/spec/build/testsuites/psxtests/psxrwlock02.yml > new file mode 100644 > index 0000000000..35244d3e03 > --- /dev/null > +++ b/spec/build/testsuites/psxtests/psxrwlock02.yml > @@ -0,0 +1,22 @@ > +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/psxrwlock02/main.c > +- testsuites/psxtests/psxrwlock02/test.c > +- cpukit/posix/src/prwlockclockrdlock.c > +- cpukit/posix/src/prwlockclockwrlock.c > +stlib: [] > +target: testsuites/psxtests/psxrwlock02.exe > +type: build > +use-after: [] > +use-before: [] > diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am > index a35f00b665..6e3c30a012 100755 > --- a/testsuites/psxtests/Makefile.am > +++ b/testsuites/psxtests/Makefile.am > @@ -811,6 +811,15 @@ psxrwlock01_CPPFLAGS = $(AM_CPPFLAGS) > $(TEST_FLAGS_psxrwlock01) \ > $(support_includes) -I$(top_srcdir)/include > endif > > +if TEST_psxrwlock02 > +psx_tests += psxrwlock02 > +psx_screens += psxrwlock02/psxrwlock02.scn > +psxrwlock02_SOURCES = psxrwlock02/main.c psxrwlock02/test.c \ > + include/pmacros.h > +psxrwlock02_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_psxrwlock02) \ > + $(support_includes) -I$(top_srcdir)/include > +endif > + > if TEST_psxsem01 > psx_tests += psxsem01 > psx_screens += psxsem01/psxsem01.scn > diff --git a/testsuites/psxtests/configure.ac > b/testsuites/psxtests/configure.ac > index 3f95010cd3..a49f809d54 100644 > --- a/testsuites/psxtests/configure.ac > +++ b/testsuites/psxtests/configure.ac > @@ -127,6 +127,7 @@ RTEMS_TEST_CHECK([psxpipe01]) > RTEMS_TEST_CHECK([psxrdwrv]) > RTEMS_TEST_CHECK([psxreaddir]) > RTEMS_TEST_CHECK([psxrwlock01]) > +RTEMS_TEST_CHECK([psxrwlock02]) > RTEMS_TEST_CHECK([psxsem01]) > RTEMS_TEST_CHECK([psxshm01]) > RTEMS_TEST_CHECK([psxshm02]) > diff --git a/testsuites/psxtests/psxrwlock02/main.c > b/testsuites/psxtests/psxrwlock02/main.c > new file mode 100644 > index 0000000000..d71218bfff > --- /dev/null > +++ b/testsuites/psxtests/psxrwlock02/main.c > @@ -0,0 +1,55 @@ > +/* > + * COPYRIGHT (c) 1989-2012. > + * On-Line Applications Research Corporation (OAR). > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ > + Add your name? BSD-2? > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#include <rtems/test-info.h> > +#include <bsp.h> > +#include <pmacros.h> > + > +/* forward declarations to avoid warnings */ > +rtems_task Init(rtems_task_argument ignored); > +void test_main(void); Init can be static and avoid the forward declaration. > + > +rtems_task Init( > + rtems_task_argument ignored > +) > +{ > + test_main(); > + rtems_test_exit( 0 ); > +} > + > +/* configuration information */ > + > +#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER > +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER > + > +#define CONFIGURE_MAXIMUM_TASKS 1 > + > +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION > + > +#define CONFIGURE_MAXIMUM_POSIX_THREADS 2 > + > +#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION > + > +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE > +#define CONFIGURE_INIT_TASK_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2) > +#define CONFIGURE_INIT_TASK_PRIORITY 2 > +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_PREEMPT This is the default so isn't needed. May just be remnant of other test. Probably should convert the Classic API init task to a pthread init thread. This is a POSIX test. > + > +#define CONFIGURE_EXTRA_TASK_STACKS RTEMS_MINIMUM_STACK_SIZE > + > +#define CONFIGURE_INIT > + > +#include <rtems/confdefs.h> > + > +/* end of file */ > diff --git a/testsuites/psxtests/psxrwlock02/test.c > b/testsuites/psxtests/psxrwlock02/test.c > new file mode 100644 > index 0000000000..50e58c5402 > --- /dev/null > +++ b/testsuites/psxtests/psxrwlock02/test.c > @@ -0,0 +1,750 @@ > +/** > + * @file > + * > + * This test exercises the POSIX RWLock manager. > + */ > + > +/* COPYRIGHT (c) 2021 Matthew Joyce > + * COPYRIGHT (c) 1989-2012. > + * On-Line Applications Research Corporation (OAR). > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * http://www.rtems.org/license/LICENSE. > + */ > + > +/* Defining to have access to function prototype in libc/include/pthread.h */ > +#define _GNU_SOURCE > + > +#ifdef HAVE_CONFIG_H > +#include "config.h" > +#endif > + > +#include "tmacros.h" > +#include <stdio.h> > +#include <errno.h> > +#include <stdlib.h> > + > +/* #define __USE_XOPEN2K XXX already defined on GNU/Linux */ > +#include <pthread.h> > + > +const char rtems_test_name[] = "PSXRWLOCK 2"; > + > +/* forward declarations to avoid warnings */ > +void *ReadLockThread(void *arg); > +void *WriteLockThread(void *arg); > +int test_main(void); > + > +#define NUMBER_THREADS 2 > +pthread_t ThreadIds[NUMBER_THREADS]; > +pthread_rwlock_t RWLock; > +clockid_t clock_id = CLOCK_MONOTONIC; > +clockid_t clock_id2 = CLOCK_REALTIME; I don't see why you have these variables. Just use the constants. I could be missing something. > + > +/* > + * Test thread to block for read lock and unlock it > + */ > +void *ReadLockThread(void *arg) > +{ > + int status; > + > + /* > + * Detach ourselves so we don't wait for a join that won't happen. > + */ > + pthread_detach( pthread_self() ); > + > + status = pthread_rwlock_rdlock(&RWLock); > + rtems_test_assert( !status ); > + > + status = pthread_rwlock_unlock(&RWLock); > + rtems_test_assert( !status ); > + return NULL; > +} > + > +/* > + * Test thread to block for write lock and unlock it > + */ > +void *WriteLockThread(void *arg) > +{ > + int status; > + > + /* > + * Detach ourselves so we don't wait for a join that won't happen. > + */ > + pthread_detach( pthread_self() ); > + > + status = pthread_rwlock_wrlock(&RWLock); > + rtems_test_assert( !status ); > + > + sleep( 2 ); > + > + status = pthread_rwlock_unlock(&RWLock); > + if ( status ) > + printf( "status=%s\n", strerror(status) ); > + rtems_test_assert( !status ); > + return NULL; > +} > + > +static void test_rwlock_pshared_init(void) > +{ > + pthread_rwlock_t rwlock; > + pthread_rwlockattr_t attr; > + int eno; > + > + eno = pthread_rwlockattr_init( &attr ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_PRIVATE ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_init( &rwlock, &attr ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_destroy( &rwlock ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_init( &rwlock, &attr ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_destroy(&rwlock); > + rtems_test_assert( eno == 0 ); > + > + attr.process_shared = -1; > + > + eno = pthread_rwlock_init( &rwlock, &attr ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlockattr_destroy( &attr ); > + rtems_test_assert( eno == 0 ); > +} > + > +static void test_rwlock_null( void ) > +{ > + struct timespec to; > + int eno; > + > + eno = pthread_rwlock_destroy( NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_init( NULL, NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_rdlock( NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( NULL, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( NULL, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( NULL, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( NULL, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_tryrdlock( NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_trywrlock( NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_unlock( NULL ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_wrlock( NULL ); > + rtems_test_assert( eno == EINVAL ); > +} > + > +static void test_rwlock_not_initialized( void ) > +{ > + pthread_rwlock_t rw; > + struct timespec to; > + int eno; > + > + memset( &rw, 0xff, sizeof( rw ) ); > + > + eno = pthread_rwlock_destroy( &rw ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_rdlock( &rw ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_tryrdlock( &rw ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_trywrlock( &rw ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_unlock( &rw ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_wrlock( &rw ); > + rtems_test_assert( eno == EINVAL ); > +} > + > +static void test_rwlock_invalid_copy( void ) > +{ > + pthread_rwlock_t rw; > + pthread_rwlock_t rw2; > + struct timespec to; > + int eno; > + > + eno = pthread_rwlock_init( &rw, NULL ); > + rtems_test_assert( eno == 0 ); > + > + memcpy( &rw2, &rw, sizeof( rw2 ) ); > + > + eno = pthread_rwlock_destroy( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_rdlock( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw2, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw2, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw2, clock_id, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw2, clock_id2, &to ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_tryrdlock( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_trywrlock( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_unlock( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_wrlock( &rw2 ); > + rtems_test_assert( eno == EINVAL ); > + > + eno = pthread_rwlock_destroy( &rw ); > + rtems_test_assert( eno == 0 ); > +} > + > +static void test_rwlock_auto_initialization( void ) > +{ > + struct timespec to; > + int eno; > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_destroy( &rw ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_destroy( &rw ); > + rtems_test_assert( eno == EINVAL ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_rdlock( &rw ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_unlock( &rw ); > + rtems_test_assert( eno == 0 ); > + > + eno = pthread_rwlock_destroy( &rw ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw, clock_id, &to ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockrdlock( &rw, clock_id2, &to ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw, clock_id, &to ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + to.tv_sec = 1; > + to.tv_nsec = 1; > + eno = pthread_rwlock_clockwrlock( &rw, clock_id2, &to ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_tryrdlock( &rw ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_trywrlock( &rw ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_unlock( &rw ); > + rtems_test_assert( eno == 0 ); > + } > + > + { > + static pthread_rwlock_t rw = PTHREAD_RWLOCK_INITIALIZER; > + > + eno = pthread_rwlock_wrlock( &rw ); > + rtems_test_assert( eno == 0 ); > + } > +} > + > +/* > + * main entry point to the test > + */ > + > +#if defined(__rtems__) > +int test_main(void) > +#else I think this can just be main() and invoke it not test_main from the init pthread. > +int main( > + int argc, > + char **argv > +) > +#endif > +{ > + pthread_rwlock_t rwlock; > + pthread_rwlockattr_t attr; > + int status; > + int p; > + int i; > + struct timespec abstime; > + > + TEST_BEGIN(); > + > + test_rwlock_pshared_init(); > + test_rwlock_null(); > + test_rwlock_not_initialized(); > + test_rwlock_invalid_copy(); > + test_rwlock_auto_initialization(); > + > + /*************** NULL POINTER CHECKS *****************/ > + status = pthread_rwlockattr_init( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_setpshared( NULL, PTHREAD_PROCESS_PRIVATE ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_setpshared( NULL, PTHREAD_PROCESS_SHARED ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_getpshared( NULL, &p ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_destroy( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + /*************** NOT INITIALIZED CHECKS *****************/ > + /* cheat visibility */ > + attr.is_initialized = 0; > + status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_getpshared( &attr, NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlockattr_destroy( &attr ); > + rtems_test_assert( status == EINVAL ); > + > + /*************** BAD PSHARED CHECK *****************/ > + status = pthread_rwlockattr_setpshared( &attr, ~PTHREAD_PROCESS_PRIVATE ); > + rtems_test_assert( status == EINVAL ); > + > + /*************** ACTUALLY WORK THIS TIME *****************/ > + status = pthread_rwlockattr_init( &attr ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_PRIVATE ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlockattr_getpshared( &attr, &p ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( p == PTHREAD_PROCESS_PRIVATE ); > + > + status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlockattr_getpshared( &attr, &p ); > + rtems_test_assert( status == 0 ); > + rtems_test_assert( p == PTHREAD_PROCESS_SHARED ); > + > + /*************** DESTROY/REUSE CHECK *****************/ > + status = pthread_rwlockattr_destroy( &attr ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlockattr_getpshared( &attr, &p ); > + rtems_test_assert( status == EINVAL ); > + > + /*************** NULL ARGUMENT CHECKS *****************/ > + abstime.tv_sec = 0; > + abstime.tv_nsec = 0; > + > + status = pthread_rwlock_init(NULL, &attr); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_destroy(NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_rdlock(NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( NULL, clock_id, &abstime); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( &rwlock, clock_id, NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( NULL, clock_id2, &abstime); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( &rwlock, clock_id2, NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_tryrdlock(NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_wrlock(NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( NULL, clock_id, &abstime ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( &rwlock, clock_id, NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( NULL, clock_id2, &abstime ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( &rwlock, clock_id2, NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_trywrlock(NULL); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_unlock(NULL); > + rtems_test_assert( status == EINVAL ); > + > + /*************** BAD ID CHECK *****************/ > + /* make a valid abstime */ > + status = clock_gettime( CLOCK_REALTIME, &abstime ); > + rtems_test_assert( !status ); > + abstime.tv_sec += 5; > + > + status = pthread_rwlock_destroy( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_rdlock( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( NULL, clock_id, &abstime); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockrdlock( NULL, clock_id2, &abstime); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_tryrdlock( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_wrlock( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( NULL, clock_id, &abstime ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_clockwrlock( NULL, clock_id2, &abstime ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_trywrlock( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + status = pthread_rwlock_unlock( NULL ); > + rtems_test_assert( status == EINVAL ); > + > + /*************** ACTUALLY CREATE ONE CHECK *****************/ > + status = pthread_rwlockattr_init( &attr ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_init( &rwlock, &attr ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_destroy( &rwlock ); > + rtems_test_assert( status == 0 ); > + > + /********* CREATE RWLOCK WITH DEFAULT ATTRIBUTES AND DESTROY IT *********/ > + status = pthread_rwlock_init( &rwlock, NULL ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_destroy( &rwlock ); > + rtems_test_assert( status == 0 ); > + > + /*************** CREATE THREADS AND LET THEM OBTAIN READLOCK > ***************/ > + status = pthread_rwlock_init( &RWLock, &attr ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_tryrdlock( &RWLock ); > + rtems_test_assert( !status ); > + > + for (i=0 ; i<NUMBER_THREADS ; i++ ) { > + status = > + pthread_create(&ThreadIds[i], NULL, ReadLockThread, &ThreadIds[i]); > + rtems_test_assert( !status ); > + > + sleep(1); > + } > + > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + sleep(1); > + > + /*************** CREATE THREADS AND LET THEM OBTAIN READLOCK > ***************/ > + status = pthread_rwlock_trywrlock( &RWLock ); > + rtems_test_assert( !status ); > + > + status = pthread_rwlock_tryrdlock( &RWLock ); > + rtems_test_assert( status == EBUSY ); > + > + for (i=0 ; i<NUMBER_THREADS ; i++ ) { > + status = > + pthread_create(&ThreadIds[i], NULL, ReadLockThread, &ThreadIds[i]); > + rtems_test_assert( !status ); > + > + sleep(1); > + } > + > + /* Attempt delete while threads are blocked */ > + status = pthread_rwlock_destroy( &RWLock ); > + rtems_test_assert( status == EBUSY ); > + > + /* now unlock it so the threads can continue */ > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + sleep(2); > + > + /*************** CREATE THREADS AND LET THEM OBTAIN WRITE LOCK > *************/ > + status = pthread_rwlock_trywrlock( &RWLock ); > + rtems_test_assert( !status ); > + > + status = pthread_rwlock_trywrlock( &RWLock ); > + rtems_test_assert( status == EBUSY ); > + > + for (i=0 ; i<NUMBER_THREADS ; i++ ) { > + status = > + pthread_create(&ThreadIds[i], NULL, WriteLockThread, &ThreadIds[i]); > + rtems_test_assert( !status ); > + > + sleep(2); > + } > + > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + sleep(6); > + > + /*************** CREATE THREADS AND LET THEM OBTAIN WRITE LOCK > *************/ > + /*************** THEN ATTEMPT TO OBTAIN A READLOCK > *************/ > + > + status = pthread_rwlock_tryrdlock( &RWLock ); > + rtems_test_assert( !status ); > + > + status = > + pthread_create(&ThreadIds[0], NULL, WriteLockThread, &ThreadIds[0]); > + rtems_test_assert( !status ); > + > + sleep(1); > + status = > + pthread_create(&ThreadIds[1], NULL, ReadLockThread, &ThreadIds[1]); > + rtems_test_assert( !status ); > + > + sleep(1); > + > + status = pthread_rwlock_tryrdlock( &RWLock ); > + rtems_test_assert( status == EBUSY ); > + > + status = pthread_rwlock_trywrlock( &RWLock ); > + rtems_test_assert( status == EBUSY ); > + > + sleep( 5 ); > + > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + sleep( 5 ); > + > + status = pthread_rwlock_destroy( &RWLock ); > + rtems_test_assert( status == 0 ); > + > + /*************** TIMEOUT ON RWLOCK MONOTONIC ***************/ > + > + status = pthread_rwlock_init( &RWLock, NULL ); > + rtems_test_assert( status == 0 ); > + > + status = clock_gettime( CLOCK_MONOTONIC, &abstime ); > + rtems_test_assert( !status ); > + > + abstime.tv_sec += 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == 0 ); > + > + abstime.tv_sec += 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + /*************** OBTAIN RWLOCK FOR READ WITH ABSTIME IN PAST > ***************/ > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == 0 ); > + > + /*************** OBTAIN RWLOCK FOR WRITE WITH ABSTIME IN PAST > ***************/ > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id, &abstime ); > + rtems_test_assert( status == 0 ); > + > + /*************** DESTROY RWLOCK ***************/ > + status = pthread_rwlock_destroy( &RWLock ); > + rtems_test_assert( status == 0 ); > + > + /*************** TIMEOUT ON RWLOCK REALTIME ***************/ > + status = pthread_rwlock_init( &RWLock, NULL ); > + rtems_test_assert( status == 0 ); > + > + status = clock_gettime( CLOCK_REALTIME, &abstime ); > + rtems_test_assert( status == 0 ); > + > + abstime.tv_sec += 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + > + abstime.tv_sec += 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == ETIMEDOUT ); > + > + /*************** OBTAIN RWLOCK FOR READ WITH ABSTIME IN PAST > ***************/ > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockrdlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + > + /*************** OBTAIN RWLOCK FOR WRITE WITH ABSTIME IN PAST > ***************/ > + status = pthread_rwlock_unlock( &RWLock ); > + rtems_test_assert( !status ); > + > + abstime.tv_sec -= 1; > + status = pthread_rwlock_clockwrlock( &RWLock, clock_id2, &abstime ); > + rtems_test_assert( status == 0 ); > + > + /*************** DESTROY RWLOCK ***************/ > + status = pthread_rwlock_destroy( &RWLock ); > + rtems_test_assert( status == 0 ); > + > + /*************** OBTAIN A LOCK AND THEN RELEASE IT TWICE ***************/ > + status = pthread_rwlock_init( &rwlock, NULL ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_unlock( &rwlock ); > + rtems_test_assert( status == 0 ); > + > + status = pthread_rwlock_unlock( &rwlock ); > + rtems_test_assert( status == 0 ); > + > + /*************** END OF TEST *****************/ > + TEST_END(); > + exit(0); > +} As a general question, did you copy an existing test and add to it? If so, you may have a lot of test cases that are not needed just based on the new additions. > -- > 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