forked from Imagelibrary/rtems
2008-01-18 Jennifer Averett <jennifer.averett@OARcorp.com>
* Makefile.am, configure.ac: * psxcleanup/Makefile.am, psxcleanup/psxcleanup.c, psxcleanup/psxcleanup.scn: New files.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2008-01-18 Jennifer Averett <jennifer.averett@OARcorp.com>
|
||||
|
||||
* Makefile.am, configure.ac:
|
||||
* psxcleanup/Makefile.am, psxcleanup/psxcleanup.c,
|
||||
psxcleanup/psxcleanup.scn: New files.
|
||||
|
||||
2008-01-18 Jennifer Averett <jennifer.averett@OARcorp.com>
|
||||
|
||||
* psx01/init.c, psxmsgq01/init.c, psxtimer01/psxtimer.c,
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ psx13/Makefile
|
||||
psxbarrier01/Makefile
|
||||
psxcancel/Makefile
|
||||
psxchroot01/Makefile
|
||||
psxcleanup/Makefile
|
||||
psxenosys/Makefile
|
||||
psxfile01/Makefile
|
||||
psxhdrs/Makefile
|
||||
|
||||
28
testsuites/psxtests/psxcleanup/Makefile.am
Normal file
28
testsuites/psxtests/psxcleanup/Makefile.am
Normal file
@@ -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
|
||||
253
testsuites/psxtests/psxcleanup/psxcleanup.c
Normal file
253
testsuites/psxtests/psxcleanup/psxcleanup.c
Normal file
@@ -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 <pthread.h> /* thread facilities */
|
||||
#include <signal.h> /* signal facilities */
|
||||
#include <unistd.h> /* sleep facilities */
|
||||
#include <sched.h> /* schedule facilities */
|
||||
#include <time.h> /* time facilities */
|
||||
#include <stdio.h> /* 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);
|
||||
}
|
||||
|
||||
6
testsuites/psxtests/psxcleanup/psxcleanup.scn
Normal file
6
testsuites/psxtests/psxcleanup/psxcleanup.scn
Normal file
@@ -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 ***
|
||||
Reference in New Issue
Block a user