From f7ad5b3e12623b865c4557d8d19e3b013a4ef6c0 Mon Sep 17 00:00:00 2001 From: Jennifer Averett Date: Fri, 18 Jan 2008 17:09:51 +0000 Subject: 2008-01-18 Jennifer Averett * Makefile.am, configure.ac: * psxcleanup/Makefile.am, psxcleanup/psxcleanup.c, psxcleanup/psxcleanup.scn: New files. --- testsuites/psxtests/ChangeLog | 6 + testsuites/psxtests/Makefile.am | 2 +- testsuites/psxtests/configure.ac | 1 + testsuites/psxtests/psxcleanup/Makefile.am | 28 +++ testsuites/psxtests/psxcleanup/psxcleanup.c | 253 ++++++++++++++++++++++++++ testsuites/psxtests/psxcleanup/psxcleanup.scn | 6 + 6 files changed, 295 insertions(+), 1 deletion(-) create mode 100644 testsuites/psxtests/psxcleanup/Makefile.am create mode 100644 testsuites/psxtests/psxcleanup/psxcleanup.c create mode 100644 testsuites/psxtests/psxcleanup/psxcleanup.scn (limited to 'testsuites/psxtests') diff --git a/testsuites/psxtests/ChangeLog b/testsuites/psxtests/ChangeLog index 4ede460e1f..df982154e7 100644 --- a/testsuites/psxtests/ChangeLog +++ b/testsuites/psxtests/ChangeLog @@ -1,3 +1,9 @@ +2008-01-18 Jennifer Averett + + * Makefile.am, configure.ac: + * psxcleanup/Makefile.am, psxcleanup/psxcleanup.c, + psxcleanup/psxcleanup.scn: New files. + 2008-01-18 Jennifer Averett * psx01/init.c, psxmsgq01/init.c, psxtimer01/psxtimer.c, diff --git a/testsuites/psxtests/Makefile.am b/testsuites/psxtests/Makefile.am index ed3ae074eb..1981c6cb45 100644 --- a/testsuites/psxtests/Makefile.am +++ b/testsuites/psxtests/Makefile.am @@ -5,7 +5,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal SUBDIRS = psxhdrs psx01 psx02 psx03 psx04 psx05 psx06 psx07 psx08 psx09 \ - psx10 psx11 psx12 psxtime psxtimer01 psxtimer02 psxcancel psxbarrier01 \ + psx10 psx11 psx12 psxcleanup psxtime psxtimer01 psxtimer02 psxcancel psxbarrier01 \ psxmsgq01 psxrwlock01 psxsem01 psxspin01 psxenosys psxsignal01 psxsysconf \ psxualarm diff --git a/testsuites/psxtests/configure.ac b/testsuites/psxtests/configure.ac index ad2fa02760..d1ec04758d 100644 --- a/testsuites/psxtests/configure.ac +++ b/testsuites/psxtests/configure.ac @@ -43,6 +43,7 @@ psx13/Makefile psxbarrier01/Makefile psxcancel/Makefile psxchroot01/Makefile +psxcleanup/Makefile psxenosys/Makefile psxfile01/Makefile psxhdrs/Makefile diff --git a/testsuites/psxtests/psxcleanup/Makefile.am b/testsuites/psxtests/psxcleanup/Makefile.am new file mode 100644 index 0000000000..915e9dc659 --- /dev/null +++ b/testsuites/psxtests/psxcleanup/Makefile.am @@ -0,0 +1,28 @@ +## +## $Id$ +## + +MANAGERS = all + +rtems_tests_PROGRAMS = psxcleanup.exe +psxcleanup_exe_SOURCES = psxcleanup.c system.h ../include/pmacros.h + +dist_rtems_tests_DATA = psxcleanup.scn + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +psxcleanup_exe_LDADD = $(MANAGERS_NOT_WANTED:%=$(PROJECT_LIB)/no-%.rel) + +AM_CPPFLAGS += -I$(top_srcdir)/include +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(psxcleanup_exe_OBJECTS) $(psxcleanup_exe_LDADD) +LINK_LIBS = $(psxcleanup_exe_LDLIBS) + +psxcleanup.exe$(EXEEXT): $(psxcleanup_exe_OBJECTS) $(psxcleanup_exe_DEPENDENCIES) + @rm -f psxcleanup.exe$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/psxtests/psxcleanup/psxcleanup.c b/testsuites/psxtests/psxcleanup/psxcleanup.c new file mode 100644 index 0000000000..f8092648ab --- /dev/null +++ b/testsuites/psxtests/psxcleanup/psxcleanup.c @@ -0,0 +1,253 @@ +/* + * + * This is a simple real-time applications XXX. + * + * Other POSIX facilities such as XXX, condition, .. is also used + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#define CONFIGURE_INIT +#include "system.h" +#include /* thread facilities */ +#include /* signal facilities */ +#include /* sleep facilities */ +#include /* schedule facilities */ +#include /* time facilities */ +#include /* console facilities */ +#include "tmacros.h" + +#define NUMBER_THREADS 2 +pthread_t ThreadIds[NUMBER_THREADS]; + +typedef struct { + pthread_mutex_t lock; + pthread_cond_t rcond; + pthread_cond_t wcond; + int lock_count; /* < 0 .. Held by writer. */ + /* > 0 .. Held by lock_count readers. */ + /* = 0 .. Held by nobody. */ + int waiting_writers; /* Count of waiting writers. */ +} lock_t; + +volatile boolean reader_cleanup_ran; +volatile boolean release_read_lock_ran; +volatile boolean writer_cleanup_ran; + +void waiting_reader_cleanup(void *arg) +{ + lock_t *l; + + reader_cleanup_ran = TRUE; + + l = (lock_t *) arg; + pthread_mutex_unlock(&l->lock); +} + +void lock_for_read(void *arg) +{ + lock_t *l = arg; + + pthread_mutex_lock(&l->lock); + pthread_cleanup_push(waiting_reader_cleanup, l); + while ((l->lock_count < 0) && (l->waiting_writers != 0)) + pthread_cond_wait(&l->rcond, &l->lock); + l->lock_count++; + reader_cleanup_ran = FALSE; + + /* + * Note the pthread_cleanup_pop executes + * waiting_reader_cleanup. + */ + pthread_cleanup_pop(1); + + if ( reader_cleanup_ran == FALSE ) { + puts( "reader cleanup did not run" ); + rtems_test_exit(0); + } +} + +void release_read_lock(void *arg) +{ + lock_t *l = arg; + + release_read_lock_ran = TRUE; + pthread_mutex_lock(&l->lock); + if (--l->lock_count == 0) + pthread_cond_signal(&l->wcond); + pthread_mutex_unlock(&l->lock); +} + +void waiting_writer_cleanup(void *arg) +{ + lock_t *l = arg; + + writer_cleanup_ran = TRUE; + + if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) { + /* + * This only happens if we have been canceled. + */ + pthread_cond_broadcast(&l->wcond); + } + pthread_mutex_unlock(&l->lock); +} + +void lock_for_write(lock_t *l) +{ + pthread_mutex_lock(&l->lock); + l->waiting_writers++; + l->lock_count = -1; + + pthread_cleanup_push(waiting_writer_cleanup, l); + + while (l->lock_count != 0) + pthread_cond_wait(&l->wcond, &l->lock); + l->lock_count = -1; + + /* + * Note the pthread_cleanup_pop executes + * waiting_writer_cleanup. + */ + writer_cleanup_ran = FALSE; + pthread_cleanup_pop(1); + + if ( writer_cleanup_ran == FALSE ) { + puts( "writer cleanup did not run" ); + rtems_test_exit(0); + } +} + +void release_write_lock(void *arg) +{ + lock_t *l = arg; + + writer_cleanup_ran = TRUE; + + /* pthread_mutex_lock(&l->lock); */ + l->lock_count = 0; + if (l->waiting_writers == 0) + pthread_cond_broadcast(&l->rcond); + else + pthread_cond_signal(&l->wcond); + /* pthread_mutex_unlock(&l->lock); */ +} + + +/* + * This function is called to initialize the read/write lock. + */ +void initialize_lock_t(lock_t *l) +{ + pthread_mutexattr_t mutexattr; /* mutex attributes */ + pthread_condattr_t condattr; /* condition attributes */ + + if (pthread_mutexattr_init (&mutexattr) != 0) { + perror ("Error in mutex attribute init\n"); + } + if (pthread_mutex_init (&l->lock,&mutexattr) != 0) { + perror ("Error in mutex init"); + } + + if (pthread_condattr_init (&condattr) != 0) { + perror ("Error in condition attribute init\n"); + } + if (pthread_cond_init (&l->wcond,&condattr) != 0) { + perror ("Error in write condition init"); + } + if (pthread_cond_init (&l->rcond,&condattr) != 0) { + perror ("Error in read condition init"); + } + + l->lock_count = 0; + l->waiting_writers = 0; +} + +void *ReaderThread(void *arg) +{ + lock_t *l = arg; + + puts("Lock for read"); + lock_for_read(l); + puts("cleanup push for read"); + pthread_cleanup_push(release_read_lock, &l->lock); + + /* Thread has read lock. */ + release_read_lock_ran = FALSE; + puts("cleanup pop for read"); + pthread_cleanup_pop(1); + + if ( release_read_lock_ran == FALSE ) { + puts( "release read lock did not run" ); + rtems_test_exit(0); + } + return NULL; +} + +void *WriterThread(void *arg) +{ + lock_t *l = arg; + + puts("Lock for write"); + lock_for_write(l); + puts("cleanup push for write"); + pthread_cleanup_push(release_write_lock, &l->lock); + + /* do nothing */ + puts("do nothing cleanup pop for write"); + pthread_cleanup_pop(0); + + /* Thread has write lock. */ + puts("cleanup pop for write"); + pthread_cleanup_pop(1); + return NULL; +} + +/* + * main entry point to the test + */ + +void *POSIX_Init ( + void *argument +) +{ + pthread_attr_t attr; /* task attributes */ + int status; + lock_t l; + + puts( "\n\n*** POSIX CLEANUP TEST ***" ); + + /*************** INITIALIZE ***************/ + initialize_lock_t(&l); + if (pthread_attr_init(&attr) != 0) { + perror ("Error in attribute init\n"); + } + + /*************** CREATE THREADS ***************/ + + status = pthread_create(&ThreadIds[0], NULL, ReaderThread, &l); + posix_service_failed( status, "pthread_create Reader" ); + + sleep(1); + + status = pthread_create(&ThreadIds[1], NULL, WriterThread, &l); + posix_service_failed( status, "pthread_create Writer" ); + + sleep(1); + + /*************** ERROR CASES ***************/ + puts("Call pthread_cleanup_push with NULL handler"); + pthread_cleanup_push(NULL, NULL); + + puts("Call pthread_cleanup_pop with no push"); + pthread_cleanup_pop(1); + + /*************** END OF TEST *****************/ + puts( "*** END OF POSIX CLEANUP TEST ***\n" ); + rtems_test_exit(0); +} + diff --git a/testsuites/psxtests/psxcleanup/psxcleanup.scn b/testsuites/psxtests/psxcleanup/psxcleanup.scn new file mode 100644 index 0000000000..23c6a718f6 --- /dev/null +++ b/testsuites/psxtests/psxcleanup/psxcleanup.scn @@ -0,0 +1,6 @@ +*** POSIX CLEANUP TEST *** +Lock for read +cleanup push for read +cleanup pop for read +Lock for write +*** END OF POSIX CLEANUP TEST *** -- cgit v1.2.3