/** * @file * * This test exercises the POSIX RWLock manager. */ /* * 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "tmacros.h" #include #include #include /* #define __USE_XOPEN2K XXX already defined on GNU/Linux */ #include const char rtems_test_name[] = "PSXRWLOCK 1"; /* forward declarations to avoid warnings */ void *ReadLockThread(void *arg); void *WriteLockThread(void *arg); int test_main(void); #if !HAVE_DECL_PTHREAD_RWLOCK_UNLOCK /* FIXME: Newlib should provide the decl. */ extern int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); #endif #define NUMBER_THREADS 2 pthread_t ThreadIds[NUMBER_THREADS]; pthread_rwlock_t RWLock; /* * 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() ); puts( "ReadThread - pthread_rwlock_rdlock(RWLock) blocking -- OK" ); status = pthread_rwlock_rdlock(&RWLock); rtems_test_assert( !status ); puts( "ReadThread - pthread_rwlock_rdlock(RWLock) unblocked -- OK" ); 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() ); puts( "WriteThread - pthread_rwlock_wrlock(RWLock) blocking -- OK" ); status = pthread_rwlock_wrlock(&RWLock); rtems_test_assert( !status ); puts( "WriteThread - pthread_rwlock_wrlock(RWLock) unblocked -- OK" ); sleep( 2 ); puts( "WriteThread - pthread_rwlock_unlock(RWLock) -- OK" ); status = pthread_rwlock_unlock(&RWLock); if ( status ) printf( "status=%s\n", strerror(status) ); rtems_test_assert( !status ); return NULL; } /* * main entry point to the test */ #if defined(__rtems__) int test_main(void) #else int main( int argc, char **argv ) #endif { pthread_rwlock_t rwlock; pthread_rwlock_t rwlock2; pthread_rwlockattr_t attr; int status; int p; int i; struct timespec abstime; TEST_BEGIN(); /*************** NULL POINTER CHECKS *****************/ puts( "pthread_rwlockattr_init( NULL ) -- EINVAL" ); status = pthread_rwlockattr_init( NULL ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_setpshared( NULL, private ) -- EINVAL" ); status = pthread_rwlockattr_setpshared( NULL, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_setpshared( NULL, shared ) -- EINVAL" ); status = pthread_rwlockattr_setpshared( NULL, PTHREAD_PROCESS_SHARED ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_getpshared( NULL, &p ) -- EINVAL" ); status = pthread_rwlockattr_getpshared( NULL, &p ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_destroy( NULL ) -- EINVAL" ); status = pthread_rwlockattr_destroy( NULL ); rtems_test_assert( status == EINVAL ); /*************** NOT INITIALIZED CHECKS *****************/ /* cheat visibility */ attr.is_initialized = 0; puts( "pthread_rwlockattr_setpshared( &attr, shared ) -- EINVAL" ); status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_getpshared( &attr, NULL ) -- EINVAL" ); status = pthread_rwlockattr_getpshared( &attr, NULL ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlockattr_destroy( &attr ) -- EINVAL" ); status = pthread_rwlockattr_destroy( &attr ); rtems_test_assert( status == EINVAL ); /*************** BAD PSHARED CHECK *****************/ puts( "pthread_rwlockattr_setpshared( &attr, private ) -- EINVAL" ); status = pthread_rwlockattr_setpshared( &attr, ~PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == EINVAL ); /*************** AUTO INITIALIZATION *****************/ rwlock = PTHREAD_RWLOCK_INITIALIZER; rwlock2 = PTHREAD_RWLOCK_INITIALIZER; status = pthread_rwlock_rdlock( &rwlock ); rtems_test_assert( status == 0 ); status = pthread_rwlock_rdlock( &rwlock2 ); rtems_test_assert( status == EINVAL ); status = pthread_rwlock_destroy( &rwlock ); rtems_test_assert( status == 0 ); status = pthread_rwlock_rdlock( &rwlock2 ); rtems_test_assert( status == 0 ); status = pthread_rwlock_destroy( &rwlock ); rtems_test_assert( status == 0 ); rwlock = PTHREAD_RWLOCK_INITIALIZER; rwlock2 = PTHREAD_RWLOCK_INITIALIZER; status = pthread_rwlock_rdlock( &rwlock ); rtems_test_assert( status == 0 ); status = pthread_rwlock_destroy( &rwlock2 ); rtems_test_assert( status == EINVAL ); status = pthread_rwlock_destroy( &rwlock ); rtems_test_assert( status == 0 ); status = pthread_rwlock_destroy( &rwlock2 ); rtems_test_assert( status == 0 ); rtems_test_assert( rwlock2 != PTHREAD_RWLOCK_INITIALIZER ); /*************** ACTUALLY WORK THIS TIME *****************/ puts( "pthread_rwlockattr_init( &attr ) -- OK" ); status = pthread_rwlockattr_init( &attr ); rtems_test_assert( status == 0 ); puts( "pthread_rwlockattr_setpshared( &attr, private ) -- OK" ); status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_PRIVATE ); rtems_test_assert( status == 0 ); puts( "pthread_rwlockattr_getpshared( &attr, &p ) -- OK" ); status = pthread_rwlockattr_getpshared( &attr, &p ); rtems_test_assert( status == 0 ); rtems_test_assert( p == PTHREAD_PROCESS_PRIVATE ); puts( "pthread_rwlockattr_setpshared( &attr, shared ) -- OK" ); status = pthread_rwlockattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); rtems_test_assert( status == 0 ); puts( "pthread_rwlockattr_getpshared( &attr, &p ) -- OK" ); status = pthread_rwlockattr_getpshared( &attr, &p ); rtems_test_assert( status == 0 ); rtems_test_assert( p == PTHREAD_PROCESS_SHARED ); /*************** DESTROY/REUSE CHECK *****************/ puts( "pthread_rwlockattr_destroy( &attr ) -- OK" ); status = pthread_rwlockattr_destroy( &attr ); rtems_test_assert( status == 0 ); puts( "pthread_rwlockattr_getpshared( &attr, &p ) destroyed -- EINVAL" ); status = pthread_rwlockattr_getpshared( &attr, &p ); rtems_test_assert( status == EINVAL ); /*************** NULL ARGUMENT CHECKS *****************/ abstime.tv_sec = 0; abstime.tv_nsec = 0; puts( "pthread_rwlock_init(NULL, &attr) -- EINVAL" ); status = pthread_rwlock_init(NULL, &attr); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_destroy(NULL) -- EINVAL" ); status = pthread_rwlock_destroy(NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_rdlock(NULL) -- EINVAL" ); status = pthread_rwlock_rdlock(NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedrdlock( NULL, &abstime) -- EINVAL" ); status = pthread_rwlock_timedrdlock( NULL, &abstime); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedrdlock( &rwlock, NULL) -- EINVAL" ); status = pthread_rwlock_timedrdlock( &rwlock, NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_tryrdlock(NULL) -- EINVAL" ); status = pthread_rwlock_tryrdlock(NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_wrlock(NULL) -- EINVAL" ); status = pthread_rwlock_wrlock(NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedwrlock( NULL, &abstime) -- EINVAL" ); status = pthread_rwlock_timedwrlock( NULL, &abstime ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedwrlock( &rwlock, NULL) -- EINVAL" ); status = pthread_rwlock_timedwrlock( &rwlock, NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_trywrlock(NULL) -- EINVAL" ); status = pthread_rwlock_trywrlock(NULL); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_unlock(NULL) -- EINVAL" ); status = pthread_rwlock_unlock(NULL); rtems_test_assert( status == EINVAL ); /*************** BAD ID CHECK *****************/ rwlock = 1; /* make a valid abstime */ puts( "clock_gettime(CLOCK_REALTIME, &abstime) -- OK" ); status = clock_gettime( CLOCK_REALTIME, &abstime ); rtems_test_assert( !status ); abstime.tv_sec += 5; puts( "pthread_rwlock_destroy(BadId) -- EINVAL" ); status = pthread_rwlock_destroy(&rwlock); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_rdlock(BadId) -- EINVAL" ); status = pthread_rwlock_rdlock(&rwlock); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedrdlock(BadId, &abstime) -- EINVAL" ); status = pthread_rwlock_timedrdlock( &rwlock, &abstime); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_tryrdlock(BadId) -- EINVAL" ); status = pthread_rwlock_tryrdlock(&rwlock); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_wrlock(BadId) -- EINVAL" ); status = pthread_rwlock_wrlock(&rwlock); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_timedwrlock(BadId, &abstime) -- EINVAL" ); status = pthread_rwlock_timedwrlock( &rwlock, &abstime ); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_trywrlock(BadId) -- EINVAL" ); status = pthread_rwlock_trywrlock(&rwlock); rtems_test_assert( status == EINVAL ); puts( "pthread_rwlock_unlock(BadId) -- EINVAL" ); status = pthread_rwlock_unlock(&rwlock); rtems_test_assert( status == EINVAL ); /*************** BAD ABSTIME CHECK *****************/ /* in the past */ abstime.tv_sec = 0; abstime.tv_nsec = 0; /* invalid tv_nsec */ abstime.tv_sec = 0; abstime.tv_nsec = 0x7fffffffL; /* XXX do we need bad time check? */ /*************** ACTUALLY CREATE ONE CHECK *****************/ puts( "pthread_rwlockattr_init( &attr ) -- OK" ); status = pthread_rwlockattr_init( &attr ); rtems_test_assert( status == 0 ); puts( "pthread_rwlock_init( &rwlock, &attr ) -- OK" ); status = pthread_rwlock_init( &rwlock, &attr ); rtems_test_assert( status == 0 ); rtems_test_assert( rwlock != 0 ); puts( "pthread_rwlock_init( &rwlock, &attr ) -- EAGAIN" ); status = pthread_rwlock_init( &rwlock, &attr ); rtems_test_assert( status == EAGAIN ); puts( "pthread_rwlock_destroy( &rwlock ) -- OK" ); status = pthread_rwlock_destroy( &rwlock ); rtems_test_assert( status == 0 ); /********* CREATE RWLOCK WITH DEFAULT ATTRIBUTES AND DESTROY IT *********/ puts( "pthread_rwlock_init( &rwlock, NULL ) -- OK" ); status = pthread_rwlock_init( &rwlock, NULL ); rtems_test_assert( status == 0 ); puts( "pthread_rwlock_destroy( &rwlock ) -- OK" ); status = pthread_rwlock_destroy( &rwlock ); rtems_test_assert( status == 0 ); /*************** CREATE THREADS AND LET THEM OBTAIN READLOCK ***************/ puts( "pthread_rwlock_init( &RWLock, &attr ) -- OK" ); status = pthread_rwlock_init( &RWLock, &attr ); rtems_test_assert( status == 0 ); puts( "pthread_rwlock_tryrdlock(RWLock) -- OK" ); status = pthread_rwlock_tryrdlock(&RWLock); rtems_test_assert( !status ); for (i=0 ; i