Automated regression test harness for libc_r. Existing tests are integrated,
a new test for POSIX semaphores was added, and examples of harness usage are included.
This commit is contained in:
parent
c30aa3de8d
commit
85d4e50332
@ -1,8 +1,123 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Tests for libc_r functionality.
|
||||
# Automated test suite for libc_r (pthreads).
|
||||
#
|
||||
|
||||
SUBDIR= mutex sigsuspend sigwait
|
||||
# File lists.
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
# Diff mode tests written in C.
|
||||
CDTESTS := hello_d.c mutex_d.c sem_d.c sigsuspend_d.c sigwait_d.c
|
||||
|
||||
# Sequence mode tests written in C.
|
||||
CSTESTS := hello_s.c
|
||||
|
||||
# C programs that are used internally by the perl-based tests. The build
|
||||
# system merely compiles these.
|
||||
BTESTS := hello_b.c
|
||||
|
||||
# Diff mode tests written in perl.
|
||||
PDTESTS :=
|
||||
|
||||
# Sequence mode tests written in perl.
|
||||
PSTESTS :=
|
||||
|
||||
# Munge the file lists to their final executable names (strip the .c).
|
||||
CDTESTS := $(CDTESTS:R)
|
||||
CSTESTS := $(CSTESTS:R)
|
||||
BTESTS := $(BTESTS:R)
|
||||
|
||||
CPPFLAGS := -D_LIBC_R_
|
||||
CFLAGS := -Wall -pipe -g3
|
||||
LDFLAGS_A := -static
|
||||
LDFLAGS_P := -pg
|
||||
LDFLAGS_S :=
|
||||
LIBS := -pthread
|
||||
|
||||
# Flags passed to verify. "-v" or "-u" may be useful.
|
||||
VFLAGS :=
|
||||
|
||||
all : default
|
||||
|
||||
# Only use the following suffixes, in order to avoid any strange built-in rules.
|
||||
.SUFFIXES :
|
||||
.SUFFIXES : .c .o .d .pl
|
||||
|
||||
# Clear out all paths, then set just one (default path) for the main build
|
||||
# directory.
|
||||
.PATH :
|
||||
.PATH : .
|
||||
|
||||
# Build the C programs.
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
$(bin)_a : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_A) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_a.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_p : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_P) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_p.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_s : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_S) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_s.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
.endfor
|
||||
|
||||
# Dependency file inclusion.
|
||||
.for depfile in $(CDTESTS:R:S/$/&_a.d/) $(CSTESTS:R:S/$/&_a.d/) \
|
||||
$(BTESTS:R:S/$/&_a.d/) $(CDTESTS:R:S/$/&_p.d/) \
|
||||
$(CSTESTS:R:S/$/&_p.d/) $(BTESTS:R:S/$/&_p.d/) \
|
||||
$(CDTESTS:R:S/$/&_s.d/) $(CSTESTS:R:S/$/&_s.d/) \
|
||||
$(BTESTS:R:S/$/&_s.d/)
|
||||
.if exists($(depfile))
|
||||
.include "$(depfile)"
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
default : check
|
||||
|
||||
tests_a : $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
tests_p : $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
tests_s : $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
|
||||
tests : tests_a tests_p tests_s
|
||||
|
||||
check_a : tests_a
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_a $(bin)
|
||||
.endfor
|
||||
@echo "Test static library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_p : tests_p
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_p $(bin)
|
||||
.endfor
|
||||
@echo "Test profile library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_s : tests_s
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_s $(bin)
|
||||
.endfor
|
||||
@echo "Test shared library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check : check_a check_p check_s
|
||||
|
||||
clean :
|
||||
rm -f *~
|
||||
rm -f *.core
|
||||
rm -f *.out
|
||||
rm -f *.perf
|
||||
rm -f *.diff
|
||||
rm -f *.gmon
|
||||
rm -f $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
rm -f $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
rm -f $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
rm -f $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
|
28
lib/libc_r/test/README
Normal file
28
lib/libc_r/test/README
Normal file
@ -0,0 +1,28 @@
|
||||
$FreeBSD$
|
||||
|
||||
This test suite is meant to test general functionality of pthreads, as well as
|
||||
provide a simple framework for regression tests. In general, this test suite
|
||||
can be used with any pthreads library, but in reality there are a number of
|
||||
libc_r-specific aspects to this test suite which would require some effort to
|
||||
get around if testing another pthreads library.
|
||||
|
||||
This test suite assumes that libc_r is installed.
|
||||
|
||||
There are two forms of test that the 'verify' script understands. The simpler
|
||||
form is the diff format, where the output of the test program is diff'ed with
|
||||
the correspondingly named .exp file. If there is diff output, the test fails.
|
||||
The sequence test format is somewhat more complex, and is documented in the
|
||||
command line usage output for verify. The advantage of this format is that it
|
||||
allows multiple tests to pass/fail within one program.
|
||||
|
||||
There is no driving need for test naming consistency, but the existing tests
|
||||
generally follow these conventions:
|
||||
|
||||
<name>_d.c <name>_d.exp : Diff mode C test and expected output file.
|
||||
<name>_s.c : Sequence mode C test.
|
||||
<name>_b*.c : Back end C program used by perl tests.
|
||||
<name>_d.pl <name>_d.pl.exp : Diff mode perl test and expected output file.
|
||||
<name>_s.pl : Sequence mode perl test.
|
||||
|
||||
<name> is something descriptive, such as "pr14685" in the case of a PR-related
|
||||
regression test, or "mutex" in the case of a test of mutexes.
|
13
lib/libc_r/test/hello_b.c
Normal file
13
lib/libc_r/test/hello_b.c
Normal file
@ -0,0 +1,13 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Back end C programs can be anything compilable.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
return 0;
|
||||
}
|
38
lib/libc_r/test/hello_d.c
Normal file
38
lib/libc_r/test/hello_d.c
Normal file
@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple diff mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
return 0;
|
||||
}
|
1
lib/libc_r/test/hello_d.exp
Normal file
1
lib/libc_r/test/hello_d.exp
Normal file
@ -0,0 +1 @@
|
||||
Hello world
|
47
lib/libc_r/test/hello_s.c
Normal file
47
lib/libc_r/test/hello_s.c
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple sequence mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "ok 1\n");
|
||||
fprintf(stderr, "ok \n");
|
||||
fprintf(stderr, "ok 3\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
fprintf(stderr, "1..3\n");
|
||||
|
||||
fprintf(stderr, "Some random text\n");
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
fprintf(stderr, "More unimportant text\n");
|
||||
if (error)
|
||||
fprintf(stderr,"Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= mutex
|
||||
SRCS= mutex.c
|
||||
NOMAN= 1
|
||||
LDFLAGS= -pthread
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -45,7 +45,7 @@
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
@ -1492,7 +1492,7 @@ int main (int argc, char *argv[])
|
||||
states[i].priority = param.sched_priority;
|
||||
assert (pthread_setschedparam (states[i].tid, SCHED_OTHER,
|
||||
¶m) == 0);
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R_)
|
||||
{
|
||||
char buf[30];
|
||||
|
290
lib/libc_r/test/mutex_d.exp
Normal file
290
lib/libc_r/test/mutex_d.exp
Normal file
@ -0,0 +1,290 @@
|
||||
|
||||
Testing pthread_mutex_init
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
|
||||
Testing pthread_mutex_destroy
|
||||
-----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
|
||||
Testing pthread_mutex_lock
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
|
||||
Testing pthread_mutex_unlock
|
||||
----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
|
||||
Testing queueing order
|
||||
----------------------
|
||||
Queueing order on a mutex - PASS
|
||||
Queueing order on a condition variable - PASS
|
||||
|
||||
Testing priority inheritence
|
||||
----------------------------
|
||||
Protype PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
|
||||
Testing priority ceilings
|
||||
-------------------------
|
||||
Protype PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
|
||||
Total tests 212, passed 212, failed 0
|
135
lib/libc_r/test/sem_d.c
Normal file
135
lib/libc_r/test/sem_d.c
Normal file
@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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(s), this list of conditions and the following disclaimer as
|
||||
* the first lines of this file unmodified other than the possible
|
||||
* addition of one or more copyright notices.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* sem test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define _REENTRANT
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define NTHREADS 10
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
sem_t * sem = (sem_t *) a_arg;
|
||||
|
||||
sem_wait(sem);
|
||||
fprintf(stderr, "Got semaphore\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
sem_t sem_a, sem_b;
|
||||
pthread_t threads[NTHREADS];
|
||||
unsigned i;
|
||||
int val;
|
||||
|
||||
fprintf(stderr, "Test begin\n");
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(-1 == sem_init(&sem_b, 1, 0));
|
||||
assert(EPERM == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_init(&sem_b, 0, 0));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(0 == val);
|
||||
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(1 == val);
|
||||
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(-1 == sem_trywait(&sem_b));
|
||||
assert(EAGAIN == errno);
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_trywait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(SEM_FAILED == sem_open("/foo", O_CREAT | O_EXCL, 0644, 0));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_close(&sem_b));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_unlink("/foo"));
|
||||
assert(ENOSYS == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_destroy(&sem_b));
|
||||
|
||||
assert(0 == sem_init(&sem_a, 0, 0));
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
assert(0 == sem_destroy(&sem_a));
|
||||
|
||||
fprintf(stderr, "Test end\n");
|
||||
return 0;
|
||||
}
|
22
lib/libc_r/test/sem_d.exp
Normal file
22
lib/libc_r/test/sem_d.exp
Normal file
@ -0,0 +1,22 @@
|
||||
Test begin
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Test end
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= sigsuspend
|
||||
SRCS= sigsuspend.c
|
||||
NOMAN= 1
|
||||
LDFLAGS= -pthread
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -40,7 +40,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
@ -75,13 +75,13 @@ sigsuspender (void *arg)
|
||||
|
||||
status = sigsuspend (&suspender_mask);
|
||||
if ((status == 0) || (errno != EINTR)) {
|
||||
printf ("Unable to suspend for signals, "
|
||||
fprintf (stderr, "Unable to suspend for signals, "
|
||||
"errno %d, return value %d\n",
|
||||
errno, status);
|
||||
exit (1);
|
||||
}
|
||||
for (i = 0; i < fifo_depth; i++)
|
||||
printf ("Sigsuspend woke up by signal %d\n",
|
||||
fprintf (stderr, "Sigsuspend woke up by signal %d\n",
|
||||
sigfifo[i]);
|
||||
fifo_depth = 0;
|
||||
}
|
||||
@ -108,8 +108,9 @@ sighandler (int signo)
|
||||
if (self == suspender_tid) {
|
||||
sigfifo[fifo_depth] = signo;
|
||||
fifo_depth++;
|
||||
printf (" -> Suspender thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
fprintf (stderr,
|
||||
" -> Suspender thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
|
||||
/* Get the current signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &set);
|
||||
@ -119,12 +120,14 @@ sighandler (int signo)
|
||||
sigaddset(&suspend_set, signo);
|
||||
|
||||
if (memcmp(&set, &suspend_set, sizeof(set)))
|
||||
printf (" >>> FAIL: sigsuspender signal handler running "
|
||||
"with incorrect mask.\n");
|
||||
fprintf (stderr,
|
||||
" >>> FAIL: sigsuspender signal handler running "
|
||||
"with incorrect mask.\n");
|
||||
}
|
||||
else
|
||||
printf (" -> Main thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
fprintf (stderr,
|
||||
" -> Main thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
}
|
||||
|
||||
|
||||
@ -132,7 +135,8 @@ static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
printf ("Unable to send thread signal, errno %d.\n", errno);
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -142,7 +146,8 @@ static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
printf ("Unable to send process signal, errno %d.\n", errno);
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -203,7 +208,7 @@ int main (int argc, char *argv[])
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
printf ("Unable to initialize thread attributes.\n");
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -211,10 +216,10 @@ int main (int argc, char *argv[])
|
||||
* Create the sigsuspender thread.
|
||||
*/
|
||||
if (pthread_create (&suspender_tid, &pattr, sigsuspender, NULL) != 0) {
|
||||
printf ("Unable to create thread, errno %d.\n", errno);
|
||||
fprintf (stderr, "Unable to create thread, errno %d.\n", errno);
|
||||
exit (1);
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R)
|
||||
pthread_set_name_np (suspender_tid, "sigsuspender");
|
||||
#endif
|
||||
|
||||
@ -227,7 +232,7 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
printf ("FAIL: sigsuspend wakes up for ignored signal "
|
||||
fprintf (stderr, "FAIL: sigsuspend wakes up for ignored signal "
|
||||
"SIGIO.\n");
|
||||
|
||||
/*
|
||||
@ -240,7 +245,8 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
printf ("FAIL: sigsuspend doesn't wake up for SIGURG.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a SIGUSR2 signal will release a sigsuspended
|
||||
@ -251,7 +257,8 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGUSR2);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR2] != 2)
|
||||
printf ("FAIL: sigsuspend doesn't wake up for SIGUSR2.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGUSR2.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal, blocked in both the main and
|
||||
@ -263,14 +270,14 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 0)
|
||||
printf ("FAIL: signal hander called for SIGUSR1.\n");
|
||||
fprintf (stderr, "FAIL: signal hander called for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
printf ("FAIL: SIGPIPE did not terminate process.\n");
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
||||
@ -279,4 +286,3 @@ int main (int argc, char *argv[])
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
8
lib/libc_r/test/sigsuspend_d.exp
Normal file
8
lib/libc_r/test/sigsuspend_d.exp
Normal file
@ -0,0 +1,8 @@
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= sigwait
|
||||
SRCS= sigwait.c
|
||||
NOMAN= 1
|
||||
LDFLAGS= -pthread
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -40,7 +40,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
@ -62,12 +62,13 @@ sigwaiter (void *arg)
|
||||
|
||||
while (sigcounts[SIGINT] == 0) {
|
||||
if (sigwait (&wait_mask, &signo) != 0) {
|
||||
printf ("Unable to wait for signal, errno %d\n",
|
||||
errno);
|
||||
fprintf (stderr,
|
||||
"Unable to wait for signal, errno %d\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
sigcounts[signo]++;
|
||||
printf ("Sigwait caught signal %d\n", signo);
|
||||
fprintf (stderr, "Sigwait caught signal %d\n", signo);
|
||||
|
||||
/* Allow the main thread to prevent the sigwait. */
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
@ -82,7 +83,7 @@ sigwaiter (void *arg)
|
||||
static void
|
||||
sighandler (int signo)
|
||||
{
|
||||
printf (" -> Signal handler caught signal %d\n", signo);
|
||||
fprintf (stderr, " -> Signal handler caught signal %d\n", signo);
|
||||
|
||||
if ((signo >= 0) && (signo <= NSIG))
|
||||
sigcounts[signo]++;
|
||||
@ -92,7 +93,8 @@ static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
printf ("Unable to send thread signal, errno %d.\n", errno);
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -101,7 +103,8 @@ static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
printf ("Unable to send process signal, errno %d.\n", errno);
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
@ -154,7 +157,7 @@ int main (int argc, char *argv[])
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
printf ("Unable to initialize thread attributes.\n");
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -163,7 +166,7 @@ int main (int argc, char *argv[])
|
||||
*/
|
||||
if ((pthread_mutexattr_init (&mattr) != 0) ||
|
||||
(pthread_mutex_init (&waiter_mutex, &mattr) != 0)) {
|
||||
printf ("Unable to create waiter mutex.\n");
|
||||
fprintf (stderr, "Unable to create waiter mutex.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
@ -171,10 +174,10 @@ int main (int argc, char *argv[])
|
||||
* Create the sigwaiter thread.
|
||||
*/
|
||||
if (pthread_create (&tid, &pattr, sigwaiter, NULL) != 0) {
|
||||
printf ("Unable to create thread.\n");
|
||||
fprintf (stderr, "Unable to create thread.\n");
|
||||
exit (1);
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(_LIBC_R_)
|
||||
pthread_set_name_np (tid, "sigwaiter");
|
||||
#endif
|
||||
|
||||
@ -187,7 +190,8 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
printf ("FAIL: sigwait wakes up for ignored signal SIGIO.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait wakes up for ignored signal SIGIO.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action of ignore, for
|
||||
@ -198,7 +202,7 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
printf ("FAIL: sigwait doesn't wake up for SIGURG.\n");
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action that terminates
|
||||
@ -209,7 +213,8 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
printf ("FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that if we install a signal handler for a previously
|
||||
@ -230,7 +235,7 @@ int main (int argc, char *argv[])
|
||||
send_thread_signal (tid, SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
printf ("FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Verify that a pending signal in the waiters mask will
|
||||
@ -248,7 +253,7 @@ int main (int argc, char *argv[])
|
||||
send_process_signal (SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 1)
|
||||
printf ("FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
/*
|
||||
* Add SIGHUP to the process pending signals. Since there is
|
||||
* a signal handler installed for SIGHUP and this signal is
|
||||
@ -260,7 +265,8 @@ int main (int argc, char *argv[])
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
printf ("FAIL: sigwait doesn't return for pending SIGHUP.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Repeat the above test using pthread_kill and SIGUSR1.
|
||||
@ -271,21 +277,23 @@ int main (int argc, char *argv[])
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 1)
|
||||
printf ("FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
/* Add SIGHUP to the waiters pending signals. */
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
/* Release the waiter thread and allow him to run. */
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
printf ("FAIL: sigwait doesn't return for pending SIGUSR1.\n");
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
printf ("FAIL: SIGPIPE did not terminate process.\n");
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
10
lib/libc_r/test/sigwait_d.exp
Normal file
10
lib/libc_r/test/sigwait_d.exp
Normal file
@ -0,0 +1,10 @@
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
-> Signal handler caught signal 1
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
505
lib/libc_r/test/verify
Executable file
505
lib/libc_r/test/verify
Executable file
@ -0,0 +1,505 @@
|
||||
#!/usr/bin/perl -w
|
||||
#-*-mode:perl-*-
|
||||
#############################################################################
|
||||
#
|
||||
# Copyright (C) 1999-2000 Jason Evans <jasone@freebsd.org>.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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(s), this list of conditions and the following disclaimer as
|
||||
# the first lines of this file unmodified other than the possible
|
||||
# addition of one or more copyright notices.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
#
|
||||
#############################################################################
|
||||
#
|
||||
# Test harness.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
# Shut off buffering.
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
|
||||
#
|
||||
# Parse command-line arguments.
|
||||
#
|
||||
use Getopt::Long;
|
||||
Getopt::Long::config("bundling"); # Allow -hv rather than forcing -h -v.
|
||||
|
||||
# Set option defaults for optional arguments.
|
||||
$opt_help = 0;
|
||||
$opt_verbose = 0;
|
||||
$opt_quiet = 0;
|
||||
$opt_srcdir = ".";
|
||||
$opt_ustats = 0;
|
||||
$opt_zero = 0;
|
||||
|
||||
$opt_retval =
|
||||
&GetOptions("h|help" => \$opt_help,
|
||||
"v|verbose" => \$opt_verbose,
|
||||
"q|quiet" => \$opt_quiet,
|
||||
"s|srcdir=s" => \$opt_srcdir,
|
||||
"u|ustats" => \$opt_ustats,
|
||||
"z|zero" => \$opt_zero
|
||||
);
|
||||
|
||||
$mode = "d";
|
||||
for ($i = 0; $i <= $#ARGV; $i++)
|
||||
{
|
||||
if (($ARGV[$i] eq "-s") || ($ARGV[$i] eq "--sequence"))
|
||||
{
|
||||
$mode = "s";
|
||||
}
|
||||
elsif (($ARGV[$i] eq "-d") || ($ARGV[$i] eq "--diff"))
|
||||
{
|
||||
$mode = "d";
|
||||
}
|
||||
elsif (-x $ARGV[$i])
|
||||
{
|
||||
if ($mode eq "s")
|
||||
{
|
||||
@STESTS = (@STESTS, $ARGV[$i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@DTESTS = (@DTESTS, $ARGV[$i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot run \"$ARGV[$i]\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt_help)
|
||||
{
|
||||
&usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($opt_retval == 0)
|
||||
{
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose && $opt_quiet)
|
||||
{
|
||||
print STDERR "-v and -q are incompatible\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($#STESTS + $#DTESTS + 2 == 0)
|
||||
{
|
||||
print STDERR "No tests specified\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Option values: h:$opt_help, v:$opt_verbose, q:$opt_quiet, "
|
||||
. "u:$opt_ustats\n";
|
||||
printf STDERR "Sequence tests (%d total): @STESTS\n", $#STESTS + 1;
|
||||
printf STDERR "Diff tests (%d total): @DTESTS\n", $#DTESTS + 1;
|
||||
}
|
||||
|
||||
#
|
||||
# Create and print header.
|
||||
#
|
||||
@TSTATS =
|
||||
(
|
||||
"--------------------------------------------------------------------------\n",
|
||||
"Test c_user c_system c_total chng\n",
|
||||
" passed/FAILED h_user h_system h_total %% chng\n"
|
||||
);
|
||||
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Run sequence test(s).
|
||||
#
|
||||
$total_utime = 0.0; # Total user time.
|
||||
$total_stime = 0.0; # Total system time.
|
||||
$total_hutime = 0.0; # Total historical user time.
|
||||
$total_hstime = 0.0; # Total historical system time.
|
||||
$total_ntime = 0.0; # Total time for tests that have historical data.
|
||||
|
||||
foreach $test (@STESTS)
|
||||
{
|
||||
# sequence mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (open (STEST_OUT, "<./$test.out"))
|
||||
{
|
||||
$num_failed_subtests = 0;
|
||||
|
||||
$_ = <STEST_OUT>;
|
||||
|
||||
if ($_ =~ /1\.\.(\d+)/)
|
||||
{
|
||||
$num_subtests = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$num_subtests = 0;
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Malformed 1..n line: \"$_\"\n";
|
||||
}
|
||||
}
|
||||
for ($subtest = 1; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
while (defined($line = <STEST_OUT>))
|
||||
{
|
||||
if ($line =~ /^not\s+ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 1;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
elsif ($line =~ /^ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 0;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (defined($line))
|
||||
{
|
||||
if (defined($test_num) && ($test_num != $subtest))
|
||||
{
|
||||
# There was no output printed for one or more tests.
|
||||
for (; $subtest < $test_num; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
if ($not)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < $num_failed_subtests)
|
||||
{
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot open output file \"$test.out\"\n";
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay,
|
||||
$num_failed_subtests, $num_subtests,
|
||||
$utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
foreach $test (@DTESTS)
|
||||
{
|
||||
# Diff mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (-e "./$test.out" && -e "$opt_srcdir/$test.exp")
|
||||
{
|
||||
`diff ./$test.out $opt_srcdir/$test.exp > ./$test.diff 2>&1`;
|
||||
if ($?)
|
||||
{
|
||||
# diff returns non-zero if there is a difference.
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR
|
||||
"Nonexistent expected output file \"$opt_srcdir/$test.exp\"\n";
|
||||
print STDERR "\$opt_srcdir is \"$opt_srcdir\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay, 0, 0, $utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
|
||||
# Print summary stats.
|
||||
$tt_str = sprintf ("%d / %d passed (%5.2f%%%%)",
|
||||
($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1),
|
||||
$#STESTS + $#DTESTS + 2,
|
||||
(($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1))
|
||||
/ ($#STESTS + $#DTESTS + 2) * 100);
|
||||
|
||||
$t_str = sprintf ("Totals %7.2f %7.2f %7.2f"
|
||||
. " %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$total_utime, $total_stime, $total_utime + $total_stime,
|
||||
($total_ntime - ($total_hutime + $total_hstime)),
|
||||
$tt_str . ' ' x (40 - length($tt_str)),
|
||||
$total_hutime, $total_hstime, $total_hutime + $total_hstime,
|
||||
($total_hutime + $total_hstime == 0.0) ? 0.0 :
|
||||
(($total_ntime
|
||||
- ($total_hutime + $total_hstime))
|
||||
/ ($total_hutime + $total_hstime) * 100));
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n",
|
||||
$t_str,
|
||||
"--------------------------------------------------------------------------\n"
|
||||
);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
# End of main execution.
|
||||
|
||||
sub run_test
|
||||
{
|
||||
my ($test) = @_;
|
||||
my ($okay) = 1;
|
||||
my ($tutime, $tstime);
|
||||
my ($utime, $stime, $cutime, $cstime);
|
||||
my (@TSTATS);
|
||||
my ($t_str);
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n");
|
||||
|
||||
$t_str = sprintf ("%s%s", $test, ' ' x (40 - length($test)));
|
||||
@TSTATS = (@TSTATS, $t_str);
|
||||
@STATS = (@STATS, @TSTATS);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
($utime, $stime, $cutime, $cstime) = times;
|
||||
`./$test $opt_srcdir > ./$test.out 2>&1`;
|
||||
($utime, $stime, $tutime, $tstime) = times;
|
||||
|
||||
# Subtract the before time from the after time.
|
||||
$tutime -= $cutime;
|
||||
$tstime -= $cstime;
|
||||
|
||||
if ($opt_zero)
|
||||
{
|
||||
if ($?)
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "\"./$test > ./$test.out 2>&1\" returned $?\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ($okay, $tutime, $tstime);
|
||||
}
|
||||
|
||||
sub print_stats
|
||||
{
|
||||
my ($test, $okay, $failed_subtests, $subtests, $utime, $stime) = @_;
|
||||
my ($hutime, $hstime);
|
||||
# my (TEST_PERF);
|
||||
my (@TSTATS);
|
||||
my ($t_str, $pass_str);
|
||||
|
||||
$pass_str = $okay ? "passed" : "*** FAILED ***";
|
||||
if ((0 != $subtests) && (!$okay))
|
||||
{
|
||||
$pass_str = $pass_str . " ($failed_subtests/$subtests failed)";
|
||||
}
|
||||
$pass_str = $pass_str . ' ' x (39 - length($pass_str));
|
||||
|
||||
if (-r "$test.perf")
|
||||
{
|
||||
if (!open (TEST_PERF, "<./$test.perf"))
|
||||
{
|
||||
print STDERR "Unable to open \"./$test.perf\"\n";
|
||||
exit 1;
|
||||
}
|
||||
$_ = <TEST_PERF>;
|
||||
|
||||
($hutime, $hstime) = split;
|
||||
close TEST_PERF;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
($utime + $stime) - ($hutime + $hstime),
|
||||
$pass_str,
|
||||
$hutime, $hstime, $hutime + $hstime,
|
||||
(($hutime + $hstime) == 0.0) ? 0.0 :
|
||||
((($utime + $stime) - ($hutime + $hstime))
|
||||
/ ($hutime + $hstime) * 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
$hutime = 0.0;
|
||||
$hstime = 0.0;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f \n"
|
||||
. " %s\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
$pass_str);
|
||||
}
|
||||
@TSTATS = ($t_str);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
if ($okay && $opt_ustats)
|
||||
{
|
||||
if (!open (TEST_PERF, ">./$test.perf"))
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Unable to update \"$test.perf\"\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print TEST_PERF "$utime $stime\n";
|
||||
close TEST_PERF;
|
||||
}
|
||||
}
|
||||
|
||||
return ($hutime, $hstime);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
print <<EOF;
|
||||
$0 usage:
|
||||
$0 [<options>] -- {[-s | -d | --sequence | --diff] <test>+}+
|
||||
|
||||
Option | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-h --help | Print usage and exit.
|
||||
-v --verbose | Verbose (incompatible with quiet).
|
||||
-q --quiet | Quiet (incompatible with verbose).
|
||||
-s --srcdir | Path to source tree (default is ".").
|
||||
-u --ustats | Update historical statistics (stored in "<test>.perf".
|
||||
-z --zero | Consider non-zero exit code to be an error.
|
||||
--------------+-------------------------------------------------------------
|
||||
|
||||
Flag | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-s --sequence | Sequence mode (default).
|
||||
| Output to stdout of the following form is expected:
|
||||
|
|
||||
| -----------------
|
||||
| 1..<n>
|
||||
| {not} ok [1]
|
||||
| {not} ok [2]
|
||||
| ...
|
||||
| {not} ok [n]
|
||||
| -----------------
|
||||
|
|
||||
| 1 <= <n> < 2^31
|
||||
|
|
||||
| Lines which do not match the patterns shown above are
|
||||
| ignored, except that the 1..<n> construct must be the first
|
||||
| line of output seen.
|
||||
|
|
||||
-d --diff | Diff mode (incompatible with sequence mode).
|
||||
| If <test>.exp exists, diff it with the output from <test> to
|
||||
| determine success or failure.
|
||||
--------------+-------------------------------------------------------------
|
||||
EOF
|
||||
}
|
@ -1,8 +1,123 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Tests for libc_r functionality.
|
||||
# Automated test suite for libc_r (pthreads).
|
||||
#
|
||||
|
||||
SUBDIR= mutex sigsuspend sigwait
|
||||
# File lists.
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
# Diff mode tests written in C.
|
||||
CDTESTS := hello_d.c mutex_d.c sem_d.c sigsuspend_d.c sigwait_d.c
|
||||
|
||||
# Sequence mode tests written in C.
|
||||
CSTESTS := hello_s.c
|
||||
|
||||
# C programs that are used internally by the perl-based tests. The build
|
||||
# system merely compiles these.
|
||||
BTESTS := hello_b.c
|
||||
|
||||
# Diff mode tests written in perl.
|
||||
PDTESTS :=
|
||||
|
||||
# Sequence mode tests written in perl.
|
||||
PSTESTS :=
|
||||
|
||||
# Munge the file lists to their final executable names (strip the .c).
|
||||
CDTESTS := $(CDTESTS:R)
|
||||
CSTESTS := $(CSTESTS:R)
|
||||
BTESTS := $(BTESTS:R)
|
||||
|
||||
CPPFLAGS := -D_LIBC_R_
|
||||
CFLAGS := -Wall -pipe -g3
|
||||
LDFLAGS_A := -static
|
||||
LDFLAGS_P := -pg
|
||||
LDFLAGS_S :=
|
||||
LIBS := -pthread
|
||||
|
||||
# Flags passed to verify. "-v" or "-u" may be useful.
|
||||
VFLAGS :=
|
||||
|
||||
all : default
|
||||
|
||||
# Only use the following suffixes, in order to avoid any strange built-in rules.
|
||||
.SUFFIXES :
|
||||
.SUFFIXES : .c .o .d .pl
|
||||
|
||||
# Clear out all paths, then set just one (default path) for the main build
|
||||
# directory.
|
||||
.PATH :
|
||||
.PATH : .
|
||||
|
||||
# Build the C programs.
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
$(bin)_a : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_A) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_a.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_p : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_P) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_p.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_s : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_S) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_s.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
.endfor
|
||||
|
||||
# Dependency file inclusion.
|
||||
.for depfile in $(CDTESTS:R:S/$/&_a.d/) $(CSTESTS:R:S/$/&_a.d/) \
|
||||
$(BTESTS:R:S/$/&_a.d/) $(CDTESTS:R:S/$/&_p.d/) \
|
||||
$(CSTESTS:R:S/$/&_p.d/) $(BTESTS:R:S/$/&_p.d/) \
|
||||
$(CDTESTS:R:S/$/&_s.d/) $(CSTESTS:R:S/$/&_s.d/) \
|
||||
$(BTESTS:R:S/$/&_s.d/)
|
||||
.if exists($(depfile))
|
||||
.include "$(depfile)"
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
default : check
|
||||
|
||||
tests_a : $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
tests_p : $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
tests_s : $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
|
||||
tests : tests_a tests_p tests_s
|
||||
|
||||
check_a : tests_a
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_a $(bin)
|
||||
.endfor
|
||||
@echo "Test static library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_p : tests_p
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_p $(bin)
|
||||
.endfor
|
||||
@echo "Test profile library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_s : tests_s
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_s $(bin)
|
||||
.endfor
|
||||
@echo "Test shared library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check : check_a check_p check_s
|
||||
|
||||
clean :
|
||||
rm -f *~
|
||||
rm -f *.core
|
||||
rm -f *.out
|
||||
rm -f *.perf
|
||||
rm -f *.diff
|
||||
rm -f *.gmon
|
||||
rm -f $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
rm -f $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
rm -f $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
rm -f $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
|
28
lib/libkse/test/README
Normal file
28
lib/libkse/test/README
Normal file
@ -0,0 +1,28 @@
|
||||
$FreeBSD$
|
||||
|
||||
This test suite is meant to test general functionality of pthreads, as well as
|
||||
provide a simple framework for regression tests. In general, this test suite
|
||||
can be used with any pthreads library, but in reality there are a number of
|
||||
libc_r-specific aspects to this test suite which would require some effort to
|
||||
get around if testing another pthreads library.
|
||||
|
||||
This test suite assumes that libc_r is installed.
|
||||
|
||||
There are two forms of test that the 'verify' script understands. The simpler
|
||||
form is the diff format, where the output of the test program is diff'ed with
|
||||
the correspondingly named .exp file. If there is diff output, the test fails.
|
||||
The sequence test format is somewhat more complex, and is documented in the
|
||||
command line usage output for verify. The advantage of this format is that it
|
||||
allows multiple tests to pass/fail within one program.
|
||||
|
||||
There is no driving need for test naming consistency, but the existing tests
|
||||
generally follow these conventions:
|
||||
|
||||
<name>_d.c <name>_d.exp : Diff mode C test and expected output file.
|
||||
<name>_s.c : Sequence mode C test.
|
||||
<name>_b*.c : Back end C program used by perl tests.
|
||||
<name>_d.pl <name>_d.pl.exp : Diff mode perl test and expected output file.
|
||||
<name>_s.pl : Sequence mode perl test.
|
||||
|
||||
<name> is something descriptive, such as "pr14685" in the case of a PR-related
|
||||
regression test, or "mutex" in the case of a test of mutexes.
|
13
lib/libkse/test/hello_b.c
Normal file
13
lib/libkse/test/hello_b.c
Normal file
@ -0,0 +1,13 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Back end C programs can be anything compilable.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
return 0;
|
||||
}
|
38
lib/libkse/test/hello_d.c
Normal file
38
lib/libkse/test/hello_d.c
Normal file
@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple diff mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
return 0;
|
||||
}
|
1
lib/libkse/test/hello_d.exp
Normal file
1
lib/libkse/test/hello_d.exp
Normal file
@ -0,0 +1 @@
|
||||
Hello world
|
47
lib/libkse/test/hello_s.c
Normal file
47
lib/libkse/test/hello_s.c
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple sequence mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "ok 1\n");
|
||||
fprintf(stderr, "ok \n");
|
||||
fprintf(stderr, "ok 3\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
fprintf(stderr, "1..3\n");
|
||||
|
||||
fprintf(stderr, "Some random text\n");
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
fprintf(stderr, "More unimportant text\n");
|
||||
if (error)
|
||||
fprintf(stderr,"Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return 0;
|
||||
}
|
1549
lib/libkse/test/mutex_d.c
Normal file
1549
lib/libkse/test/mutex_d.c
Normal file
File diff suppressed because it is too large
Load Diff
290
lib/libkse/test/mutex_d.exp
Normal file
290
lib/libkse/test/mutex_d.exp
Normal file
@ -0,0 +1,290 @@
|
||||
|
||||
Testing pthread_mutex_init
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
|
||||
Testing pthread_mutex_destroy
|
||||
-----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
|
||||
Testing pthread_mutex_lock
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
|
||||
Testing pthread_mutex_unlock
|
||||
----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
|
||||
Testing queueing order
|
||||
----------------------
|
||||
Queueing order on a mutex - PASS
|
||||
Queueing order on a condition variable - PASS
|
||||
|
||||
Testing priority inheritence
|
||||
----------------------------
|
||||
Protype PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
|
||||
Testing priority ceilings
|
||||
-------------------------
|
||||
Protype PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
|
||||
Total tests 212, passed 212, failed 0
|
135
lib/libkse/test/sem_d.c
Normal file
135
lib/libkse/test/sem_d.c
Normal file
@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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(s), this list of conditions and the following disclaimer as
|
||||
* the first lines of this file unmodified other than the possible
|
||||
* addition of one or more copyright notices.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* sem test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define _REENTRANT
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define NTHREADS 10
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
sem_t * sem = (sem_t *) a_arg;
|
||||
|
||||
sem_wait(sem);
|
||||
fprintf(stderr, "Got semaphore\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
sem_t sem_a, sem_b;
|
||||
pthread_t threads[NTHREADS];
|
||||
unsigned i;
|
||||
int val;
|
||||
|
||||
fprintf(stderr, "Test begin\n");
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(-1 == sem_init(&sem_b, 1, 0));
|
||||
assert(EPERM == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_init(&sem_b, 0, 0));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(0 == val);
|
||||
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(1 == val);
|
||||
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(-1 == sem_trywait(&sem_b));
|
||||
assert(EAGAIN == errno);
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_trywait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(SEM_FAILED == sem_open("/foo", O_CREAT | O_EXCL, 0644, 0));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_close(&sem_b));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_unlink("/foo"));
|
||||
assert(ENOSYS == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_destroy(&sem_b));
|
||||
|
||||
assert(0 == sem_init(&sem_a, 0, 0));
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
assert(0 == sem_destroy(&sem_a));
|
||||
|
||||
fprintf(stderr, "Test end\n");
|
||||
return 0;
|
||||
}
|
22
lib/libkse/test/sem_d.exp
Normal file
22
lib/libkse/test/sem_d.exp
Normal file
@ -0,0 +1,22 @@
|
||||
Test begin
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Test end
|
288
lib/libkse/test/sigsuspend_d.c
Normal file
288
lib/libkse/test/sigsuspend_d.c
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Daniel M. Eischen.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
static int sigcounts[NSIG + 1];
|
||||
static int sigfifo[NSIG + 1];
|
||||
static int fifo_depth = 0;
|
||||
static sigset_t suspender_mask;
|
||||
static pthread_t suspender_tid;
|
||||
|
||||
|
||||
static void *
|
||||
sigsuspender (void *arg)
|
||||
{
|
||||
int save_count, status, i;
|
||||
sigset_t run_mask;
|
||||
|
||||
/* Run with all signals blocked. */
|
||||
sigfillset (&run_mask);
|
||||
sigprocmask (SIG_SETMASK, &run_mask, NULL);
|
||||
|
||||
/* Allow these signals to wake us up during a sigsuspend. */
|
||||
sigfillset (&suspender_mask); /* Default action */
|
||||
sigdelset (&suspender_mask, SIGINT); /* terminate */
|
||||
sigdelset (&suspender_mask, SIGHUP); /* terminate */
|
||||
sigdelset (&suspender_mask, SIGQUIT); /* create core image */
|
||||
sigdelset (&suspender_mask, SIGURG); /* ignore */
|
||||
sigdelset (&suspender_mask, SIGIO); /* ignore */
|
||||
sigdelset (&suspender_mask, SIGUSR2); /* terminate */
|
||||
|
||||
while (sigcounts[SIGINT] == 0) {
|
||||
save_count = sigcounts[SIGUSR2];
|
||||
|
||||
status = sigsuspend (&suspender_mask);
|
||||
if ((status == 0) || (errno != EINTR)) {
|
||||
fprintf (stderr, "Unable to suspend for signals, "
|
||||
"errno %d, return value %d\n",
|
||||
errno, status);
|
||||
exit (1);
|
||||
}
|
||||
for (i = 0; i < fifo_depth; i++)
|
||||
fprintf (stderr, "Sigsuspend woke up by signal %d\n",
|
||||
sigfifo[i]);
|
||||
fifo_depth = 0;
|
||||
}
|
||||
|
||||
pthread_exit (arg);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sighandler (int signo)
|
||||
{
|
||||
sigset_t set, suspend_set;
|
||||
pthread_t self;
|
||||
|
||||
if ((signo >= 0) && (signo <= NSIG))
|
||||
sigcounts[signo]++;
|
||||
|
||||
/*
|
||||
* If we are running on behalf of the suspender thread,
|
||||
* ensure that we have the correct mask set.
|
||||
*/
|
||||
self = pthread_self ();
|
||||
if (self == suspender_tid) {
|
||||
sigfifo[fifo_depth] = signo;
|
||||
fifo_depth++;
|
||||
fprintf (stderr,
|
||||
" -> Suspender thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
|
||||
/* Get the current signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &set);
|
||||
|
||||
/* The handler should run with the current signal masked. */
|
||||
suspend_set = suspender_mask;
|
||||
sigaddset(&suspend_set, signo);
|
||||
|
||||
if (memcmp(&set, &suspend_set, sizeof(set)))
|
||||
fprintf (stderr,
|
||||
" >>> FAIL: sigsuspender signal handler running "
|
||||
"with incorrect mask.\n");
|
||||
}
|
||||
else
|
||||
fprintf (stderr,
|
||||
" -> Main thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
pthread_attr_t pattr;
|
||||
void * exit_status;
|
||||
struct sigaction act;
|
||||
sigset_t oldset;
|
||||
sigset_t newset;
|
||||
|
||||
/* Initialize our signal counts. */
|
||||
memset ((void *) sigcounts, 0, NSIG * sizeof (int));
|
||||
|
||||
/* Ignore signal SIGIO. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGIO);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGIO, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGURG. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGURG);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGURG, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGXCPU */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGXCPU);
|
||||
sigaction (SIGXCPU, &act, NULL);
|
||||
|
||||
/* Get our current signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &oldset);
|
||||
|
||||
/* Mask out SIGUSR1 and SIGUSR2. */
|
||||
newset = oldset;
|
||||
sigaddset (&newset, SIGUSR1);
|
||||
sigaddset (&newset, SIGUSR2);
|
||||
sigprocmask (SIG_SETMASK, &newset, NULL);
|
||||
|
||||
/* Install a signal handler for SIGUSR1 */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGUSR1);
|
||||
sigaction (SIGUSR1, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGUSR2 */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGUSR2);
|
||||
sigaction (SIGUSR2, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize the thread attribute.
|
||||
*/
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the sigsuspender thread.
|
||||
*/
|
||||
if (pthread_create (&suspender_tid, &pattr, sigsuspender, NULL) != 0) {
|
||||
fprintf (stderr, "Unable to create thread, errno %d.\n", errno);
|
||||
exit (1);
|
||||
}
|
||||
#if defined(_LIBC_R)
|
||||
pthread_set_name_np (suspender_tid, "sigsuspender");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify that an ignored signal doesn't cause a wakeup.
|
||||
* We don't have a handler installed for SIGIO.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGIO);
|
||||
sleep (1);
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
fprintf (stderr, "FAIL: sigsuspend wakes up for ignored signal "
|
||||
"SIGIO.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action of ignore, for
|
||||
* which we have a signal handler installed, will release a
|
||||
* sigsuspend.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGURG);
|
||||
sleep (1);
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a SIGUSR2 signal will release a sigsuspended
|
||||
* thread.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGUSR2);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR2);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR2] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGUSR2.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal, blocked in both the main and
|
||||
* sigsuspender threads, does not cause the signal handler
|
||||
* to be called.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGUSR1);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 0)
|
||||
fprintf (stderr, "FAIL: signal hander called for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
||||
*/
|
||||
pthread_join (suspender_tid, &exit_status);
|
||||
|
||||
return (0);
|
||||
}
|
8
lib/libkse/test/sigsuspend_d.exp
Normal file
8
lib/libkse/test/sigsuspend_d.exp
Normal file
@ -0,0 +1,8 @@
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
304
lib/libkse/test/sigwait_d.c
Normal file
304
lib/libkse/test/sigwait_d.c
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Daniel M. Eischen.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
static int sigcounts[NSIG + 1];
|
||||
static sigset_t wait_mask;
|
||||
static pthread_mutex_t waiter_mutex;
|
||||
|
||||
|
||||
static void *
|
||||
sigwaiter (void *arg)
|
||||
{
|
||||
int signo;
|
||||
sigset_t mask;
|
||||
|
||||
/* Block SIGHUP */
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGHUP);
|
||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||
|
||||
while (sigcounts[SIGINT] == 0) {
|
||||
if (sigwait (&wait_mask, &signo) != 0) {
|
||||
fprintf (stderr,
|
||||
"Unable to wait for signal, errno %d\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
sigcounts[signo]++;
|
||||
fprintf (stderr, "Sigwait caught signal %d\n", signo);
|
||||
|
||||
/* Allow the main thread to prevent the sigwait. */
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
}
|
||||
|
||||
pthread_exit (arg);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sighandler (int signo)
|
||||
{
|
||||
fprintf (stderr, " -> Signal handler caught signal %d\n", signo);
|
||||
|
||||
if ((signo >= 0) && (signo <= NSIG))
|
||||
sigcounts[signo]++;
|
||||
}
|
||||
|
||||
static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
pthread_mutexattr_t mattr;
|
||||
pthread_attr_t pattr;
|
||||
pthread_t tid;
|
||||
void * exit_status;
|
||||
struct sigaction act;
|
||||
|
||||
/* Initialize our signal counts. */
|
||||
memset ((void *) sigcounts, 0, NSIG * sizeof (int));
|
||||
|
||||
/* Setup our wait mask. */
|
||||
sigemptyset (&wait_mask); /* Default action */
|
||||
sigaddset (&wait_mask, SIGHUP); /* terminate */
|
||||
sigaddset (&wait_mask, SIGINT); /* terminate */
|
||||
sigaddset (&wait_mask, SIGQUIT); /* create core image */
|
||||
sigaddset (&wait_mask, SIGURG); /* ignore */
|
||||
sigaddset (&wait_mask, SIGIO); /* ignore */
|
||||
sigaddset (&wait_mask, SIGUSR1); /* terminate */
|
||||
|
||||
/* Ignore signals SIGHUP and SIGIO. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGHUP);
|
||||
sigaddset (&act.sa_mask, SIGIO);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGHUP, &act, NULL);
|
||||
sigaction (SIGIO, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGURG */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGURG);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGURG, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGXCPU */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGXCPU);
|
||||
sigaction (SIGXCPU, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize the thread attribute.
|
||||
*/
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and create a mutex.
|
||||
*/
|
||||
if ((pthread_mutexattr_init (&mattr) != 0) ||
|
||||
(pthread_mutex_init (&waiter_mutex, &mattr) != 0)) {
|
||||
fprintf (stderr, "Unable to create waiter mutex.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the sigwaiter thread.
|
||||
*/
|
||||
if (pthread_create (&tid, &pattr, sigwaiter, NULL) != 0) {
|
||||
fprintf (stderr, "Unable to create thread.\n");
|
||||
exit (1);
|
||||
}
|
||||
#if defined(_LIBC_R_)
|
||||
pthread_set_name_np (tid, "sigwaiter");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify that an ignored signal doesn't cause a wakeup.
|
||||
* We don't have a handler installed for SIGIO.
|
||||
*/
|
||||
send_thread_signal (tid, SIGIO);
|
||||
sleep (1);
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait wakes up for ignored signal SIGIO.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action of ignore, for
|
||||
* which we have a signal handler installed, will release a sigwait.
|
||||
*/
|
||||
send_thread_signal (tid, SIGURG);
|
||||
sleep (1);
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action that terminates
|
||||
* the process will release a sigwait.
|
||||
*/
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that if we install a signal handler for a previously
|
||||
* ignored signal, an occurrence of this signal will release
|
||||
* the (already waiting) sigwait.
|
||||
*/
|
||||
|
||||
/* Install a signal handler for SIGHUP. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGHUP);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGHUP, &act, NULL);
|
||||
|
||||
/* Sending SIGHUP should release the sigwait. */
|
||||
send_process_signal (SIGHUP);
|
||||
sleep (1);
|
||||
send_thread_signal (tid, SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Verify that a pending signal in the waiters mask will
|
||||
* cause sigwait to return the pending signal. We do this
|
||||
* by taking the waiters mutex and signaling the waiter to
|
||||
* release him from the sigwait. The waiter will block
|
||||
* on taking the mutex, and we can then send the waiter a
|
||||
* signal which should be added to his pending signals.
|
||||
* The next time the waiter does a sigwait, he should
|
||||
* return with the pending signal.
|
||||
*/
|
||||
sigcounts[SIGHUP] = 0;
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
/* Release the waiter from sigwait. */
|
||||
send_process_signal (SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 1)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
/*
|
||||
* Add SIGHUP to the process pending signals. Since there is
|
||||
* a signal handler installed for SIGHUP and this signal is
|
||||
* blocked from the waiter thread and unblocked in the main
|
||||
* thread, the signal handler should be called once for SIGHUP.
|
||||
*/
|
||||
send_process_signal (SIGHUP);
|
||||
/* Release the waiter thread and allow him to run. */
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Repeat the above test using pthread_kill and SIGUSR1.
|
||||
*/
|
||||
sigcounts[SIGUSR1] = 0;
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
/* Release the waiter from sigwait. */
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 1)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
/* Add SIGHUP to the waiters pending signals. */
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
/* Release the waiter thread and allow him to run. */
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
||||
*/
|
||||
pthread_join (tid, &exit_status);
|
||||
|
||||
return (0);
|
||||
}
|
10
lib/libkse/test/sigwait_d.exp
Normal file
10
lib/libkse/test/sigwait_d.exp
Normal file
@ -0,0 +1,10 @@
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
-> Signal handler caught signal 1
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
505
lib/libkse/test/verify
Normal file
505
lib/libkse/test/verify
Normal file
@ -0,0 +1,505 @@
|
||||
#!/usr/bin/perl -w
|
||||
#-*-mode:perl-*-
|
||||
#############################################################################
|
||||
#
|
||||
# Copyright (C) 1999-2000 Jason Evans <jasone@freebsd.org>.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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(s), this list of conditions and the following disclaimer as
|
||||
# the first lines of this file unmodified other than the possible
|
||||
# addition of one or more copyright notices.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
#
|
||||
#############################################################################
|
||||
#
|
||||
# Test harness.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
# Shut off buffering.
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
|
||||
#
|
||||
# Parse command-line arguments.
|
||||
#
|
||||
use Getopt::Long;
|
||||
Getopt::Long::config("bundling"); # Allow -hv rather than forcing -h -v.
|
||||
|
||||
# Set option defaults for optional arguments.
|
||||
$opt_help = 0;
|
||||
$opt_verbose = 0;
|
||||
$opt_quiet = 0;
|
||||
$opt_srcdir = ".";
|
||||
$opt_ustats = 0;
|
||||
$opt_zero = 0;
|
||||
|
||||
$opt_retval =
|
||||
&GetOptions("h|help" => \$opt_help,
|
||||
"v|verbose" => \$opt_verbose,
|
||||
"q|quiet" => \$opt_quiet,
|
||||
"s|srcdir=s" => \$opt_srcdir,
|
||||
"u|ustats" => \$opt_ustats,
|
||||
"z|zero" => \$opt_zero
|
||||
);
|
||||
|
||||
$mode = "d";
|
||||
for ($i = 0; $i <= $#ARGV; $i++)
|
||||
{
|
||||
if (($ARGV[$i] eq "-s") || ($ARGV[$i] eq "--sequence"))
|
||||
{
|
||||
$mode = "s";
|
||||
}
|
||||
elsif (($ARGV[$i] eq "-d") || ($ARGV[$i] eq "--diff"))
|
||||
{
|
||||
$mode = "d";
|
||||
}
|
||||
elsif (-x $ARGV[$i])
|
||||
{
|
||||
if ($mode eq "s")
|
||||
{
|
||||
@STESTS = (@STESTS, $ARGV[$i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@DTESTS = (@DTESTS, $ARGV[$i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot run \"$ARGV[$i]\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt_help)
|
||||
{
|
||||
&usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($opt_retval == 0)
|
||||
{
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose && $opt_quiet)
|
||||
{
|
||||
print STDERR "-v and -q are incompatible\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($#STESTS + $#DTESTS + 2 == 0)
|
||||
{
|
||||
print STDERR "No tests specified\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Option values: h:$opt_help, v:$opt_verbose, q:$opt_quiet, "
|
||||
. "u:$opt_ustats\n";
|
||||
printf STDERR "Sequence tests (%d total): @STESTS\n", $#STESTS + 1;
|
||||
printf STDERR "Diff tests (%d total): @DTESTS\n", $#DTESTS + 1;
|
||||
}
|
||||
|
||||
#
|
||||
# Create and print header.
|
||||
#
|
||||
@TSTATS =
|
||||
(
|
||||
"--------------------------------------------------------------------------\n",
|
||||
"Test c_user c_system c_total chng\n",
|
||||
" passed/FAILED h_user h_system h_total %% chng\n"
|
||||
);
|
||||
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Run sequence test(s).
|
||||
#
|
||||
$total_utime = 0.0; # Total user time.
|
||||
$total_stime = 0.0; # Total system time.
|
||||
$total_hutime = 0.0; # Total historical user time.
|
||||
$total_hstime = 0.0; # Total historical system time.
|
||||
$total_ntime = 0.0; # Total time for tests that have historical data.
|
||||
|
||||
foreach $test (@STESTS)
|
||||
{
|
||||
# sequence mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (open (STEST_OUT, "<./$test.out"))
|
||||
{
|
||||
$num_failed_subtests = 0;
|
||||
|
||||
$_ = <STEST_OUT>;
|
||||
|
||||
if ($_ =~ /1\.\.(\d+)/)
|
||||
{
|
||||
$num_subtests = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$num_subtests = 0;
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Malformed 1..n line: \"$_\"\n";
|
||||
}
|
||||
}
|
||||
for ($subtest = 1; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
while (defined($line = <STEST_OUT>))
|
||||
{
|
||||
if ($line =~ /^not\s+ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 1;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
elsif ($line =~ /^ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 0;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (defined($line))
|
||||
{
|
||||
if (defined($test_num) && ($test_num != $subtest))
|
||||
{
|
||||
# There was no output printed for one or more tests.
|
||||
for (; $subtest < $test_num; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
if ($not)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < $num_failed_subtests)
|
||||
{
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot open output file \"$test.out\"\n";
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay,
|
||||
$num_failed_subtests, $num_subtests,
|
||||
$utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
foreach $test (@DTESTS)
|
||||
{
|
||||
# Diff mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (-e "./$test.out" && -e "$opt_srcdir/$test.exp")
|
||||
{
|
||||
`diff ./$test.out $opt_srcdir/$test.exp > ./$test.diff 2>&1`;
|
||||
if ($?)
|
||||
{
|
||||
# diff returns non-zero if there is a difference.
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR
|
||||
"Nonexistent expected output file \"$opt_srcdir/$test.exp\"\n";
|
||||
print STDERR "\$opt_srcdir is \"$opt_srcdir\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay, 0, 0, $utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
|
||||
# Print summary stats.
|
||||
$tt_str = sprintf ("%d / %d passed (%5.2f%%%%)",
|
||||
($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1),
|
||||
$#STESTS + $#DTESTS + 2,
|
||||
(($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1))
|
||||
/ ($#STESTS + $#DTESTS + 2) * 100);
|
||||
|
||||
$t_str = sprintf ("Totals %7.2f %7.2f %7.2f"
|
||||
. " %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$total_utime, $total_stime, $total_utime + $total_stime,
|
||||
($total_ntime - ($total_hutime + $total_hstime)),
|
||||
$tt_str . ' ' x (40 - length($tt_str)),
|
||||
$total_hutime, $total_hstime, $total_hutime + $total_hstime,
|
||||
($total_hutime + $total_hstime == 0.0) ? 0.0 :
|
||||
(($total_ntime
|
||||
- ($total_hutime + $total_hstime))
|
||||
/ ($total_hutime + $total_hstime) * 100));
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n",
|
||||
$t_str,
|
||||
"--------------------------------------------------------------------------\n"
|
||||
);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
# End of main execution.
|
||||
|
||||
sub run_test
|
||||
{
|
||||
my ($test) = @_;
|
||||
my ($okay) = 1;
|
||||
my ($tutime, $tstime);
|
||||
my ($utime, $stime, $cutime, $cstime);
|
||||
my (@TSTATS);
|
||||
my ($t_str);
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n");
|
||||
|
||||
$t_str = sprintf ("%s%s", $test, ' ' x (40 - length($test)));
|
||||
@TSTATS = (@TSTATS, $t_str);
|
||||
@STATS = (@STATS, @TSTATS);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
($utime, $stime, $cutime, $cstime) = times;
|
||||
`./$test $opt_srcdir > ./$test.out 2>&1`;
|
||||
($utime, $stime, $tutime, $tstime) = times;
|
||||
|
||||
# Subtract the before time from the after time.
|
||||
$tutime -= $cutime;
|
||||
$tstime -= $cstime;
|
||||
|
||||
if ($opt_zero)
|
||||
{
|
||||
if ($?)
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "\"./$test > ./$test.out 2>&1\" returned $?\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ($okay, $tutime, $tstime);
|
||||
}
|
||||
|
||||
sub print_stats
|
||||
{
|
||||
my ($test, $okay, $failed_subtests, $subtests, $utime, $stime) = @_;
|
||||
my ($hutime, $hstime);
|
||||
# my (TEST_PERF);
|
||||
my (@TSTATS);
|
||||
my ($t_str, $pass_str);
|
||||
|
||||
$pass_str = $okay ? "passed" : "*** FAILED ***";
|
||||
if ((0 != $subtests) && (!$okay))
|
||||
{
|
||||
$pass_str = $pass_str . " ($failed_subtests/$subtests failed)";
|
||||
}
|
||||
$pass_str = $pass_str . ' ' x (39 - length($pass_str));
|
||||
|
||||
if (-r "$test.perf")
|
||||
{
|
||||
if (!open (TEST_PERF, "<./$test.perf"))
|
||||
{
|
||||
print STDERR "Unable to open \"./$test.perf\"\n";
|
||||
exit 1;
|
||||
}
|
||||
$_ = <TEST_PERF>;
|
||||
|
||||
($hutime, $hstime) = split;
|
||||
close TEST_PERF;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
($utime + $stime) - ($hutime + $hstime),
|
||||
$pass_str,
|
||||
$hutime, $hstime, $hutime + $hstime,
|
||||
(($hutime + $hstime) == 0.0) ? 0.0 :
|
||||
((($utime + $stime) - ($hutime + $hstime))
|
||||
/ ($hutime + $hstime) * 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
$hutime = 0.0;
|
||||
$hstime = 0.0;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f \n"
|
||||
. " %s\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
$pass_str);
|
||||
}
|
||||
@TSTATS = ($t_str);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
if ($okay && $opt_ustats)
|
||||
{
|
||||
if (!open (TEST_PERF, ">./$test.perf"))
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Unable to update \"$test.perf\"\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print TEST_PERF "$utime $stime\n";
|
||||
close TEST_PERF;
|
||||
}
|
||||
}
|
||||
|
||||
return ($hutime, $hstime);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
print <<EOF;
|
||||
$0 usage:
|
||||
$0 [<options>] -- {[-s | -d | --sequence | --diff] <test>+}+
|
||||
|
||||
Option | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-h --help | Print usage and exit.
|
||||
-v --verbose | Verbose (incompatible with quiet).
|
||||
-q --quiet | Quiet (incompatible with verbose).
|
||||
-s --srcdir | Path to source tree (default is ".").
|
||||
-u --ustats | Update historical statistics (stored in "<test>.perf".
|
||||
-z --zero | Consider non-zero exit code to be an error.
|
||||
--------------+-------------------------------------------------------------
|
||||
|
||||
Flag | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-s --sequence | Sequence mode (default).
|
||||
| Output to stdout of the following form is expected:
|
||||
|
|
||||
| -----------------
|
||||
| 1..<n>
|
||||
| {not} ok [1]
|
||||
| {not} ok [2]
|
||||
| ...
|
||||
| {not} ok [n]
|
||||
| -----------------
|
||||
|
|
||||
| 1 <= <n> < 2^31
|
||||
|
|
||||
| Lines which do not match the patterns shown above are
|
||||
| ignored, except that the 1..<n> construct must be the first
|
||||
| line of output seen.
|
||||
|
|
||||
-d --diff | Diff mode (incompatible with sequence mode).
|
||||
| If <test>.exp exists, diff it with the output from <test> to
|
||||
| determine success or failure.
|
||||
--------------+-------------------------------------------------------------
|
||||
EOF
|
||||
}
|
@ -1,8 +1,123 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# Tests for libc_r functionality.
|
||||
# Automated test suite for libc_r (pthreads).
|
||||
#
|
||||
|
||||
SUBDIR= mutex sigsuspend sigwait
|
||||
# File lists.
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
# Diff mode tests written in C.
|
||||
CDTESTS := hello_d.c mutex_d.c sem_d.c sigsuspend_d.c sigwait_d.c
|
||||
|
||||
# Sequence mode tests written in C.
|
||||
CSTESTS := hello_s.c
|
||||
|
||||
# C programs that are used internally by the perl-based tests. The build
|
||||
# system merely compiles these.
|
||||
BTESTS := hello_b.c
|
||||
|
||||
# Diff mode tests written in perl.
|
||||
PDTESTS :=
|
||||
|
||||
# Sequence mode tests written in perl.
|
||||
PSTESTS :=
|
||||
|
||||
# Munge the file lists to their final executable names (strip the .c).
|
||||
CDTESTS := $(CDTESTS:R)
|
||||
CSTESTS := $(CSTESTS:R)
|
||||
BTESTS := $(BTESTS:R)
|
||||
|
||||
CPPFLAGS := -D_LIBC_R_
|
||||
CFLAGS := -Wall -pipe -g3
|
||||
LDFLAGS_A := -static
|
||||
LDFLAGS_P := -pg
|
||||
LDFLAGS_S :=
|
||||
LIBS := -pthread
|
||||
|
||||
# Flags passed to verify. "-v" or "-u" may be useful.
|
||||
VFLAGS :=
|
||||
|
||||
all : default
|
||||
|
||||
# Only use the following suffixes, in order to avoid any strange built-in rules.
|
||||
.SUFFIXES :
|
||||
.SUFFIXES : .c .o .d .pl
|
||||
|
||||
# Clear out all paths, then set just one (default path) for the main build
|
||||
# directory.
|
||||
.PATH :
|
||||
.PATH : .
|
||||
|
||||
# Build the C programs.
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
$(bin)_a : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_A) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_a.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_p : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_P) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_p.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
|
||||
$(bin)_s : $(bin:S/$/&.c/)
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $(bin:S/$/&.c/) -o $(@:S/$/&.o/)
|
||||
$(CC) -o $@ $(@:S/$/&.o/) $(LDFLAGS_S) $(LIBS)
|
||||
@$(SHELL) -ec "$(CC) -M $(CPPFLAGS) $(bin:S/$/&.c/) | sed \"s/\($(bin:T)\)\.o\([ :]*\)/$(bin:H:S!/!\\/!g)\/\1_s.o \2/g\" > $(@:R:S/$/&.d/)"
|
||||
.endfor
|
||||
|
||||
# Dependency file inclusion.
|
||||
.for depfile in $(CDTESTS:R:S/$/&_a.d/) $(CSTESTS:R:S/$/&_a.d/) \
|
||||
$(BTESTS:R:S/$/&_a.d/) $(CDTESTS:R:S/$/&_p.d/) \
|
||||
$(CSTESTS:R:S/$/&_p.d/) $(BTESTS:R:S/$/&_p.d/) \
|
||||
$(CDTESTS:R:S/$/&_s.d/) $(CSTESTS:R:S/$/&_s.d/) \
|
||||
$(BTESTS:R:S/$/&_s.d/)
|
||||
.if exists($(depfile))
|
||||
.include "$(depfile)"
|
||||
.endif
|
||||
.endfor
|
||||
|
||||
default : check
|
||||
|
||||
tests_a : $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
tests_p : $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
tests_s : $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
|
||||
tests : tests_a tests_p tests_s
|
||||
|
||||
check_a : tests_a
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_a $(bin)
|
||||
.endfor
|
||||
@echo "Test static library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_p : tests_p
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_p $(bin)
|
||||
.endfor
|
||||
@echo "Test profile library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check_s : tests_s
|
||||
.for bin in $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
@cp $(bin)_s $(bin)
|
||||
.endfor
|
||||
@echo "Test shared library:"
|
||||
@./verify $(VFLAGS) -- -d $(CDTESTS) $(PDTESTS) -s $(CSTESTS) $(PSTESTS)
|
||||
|
||||
check : check_a check_p check_s
|
||||
|
||||
clean :
|
||||
rm -f *~
|
||||
rm -f *.core
|
||||
rm -f *.out
|
||||
rm -f *.perf
|
||||
rm -f *.diff
|
||||
rm -f *.gmon
|
||||
rm -f $(CDTESTS) $(CSTESTS) $(BTESTS)
|
||||
rm -f $(CDTESTS:S/$/&_a/) $(CSTESTS:S/$/&_a/) $(BTESTS:S/$/&_a/)
|
||||
rm -f $(CDTESTS:S/$/&_p/) $(CSTESTS:S/$/&_p/) $(BTESTS:S/$/&_p/)
|
||||
rm -f $(CDTESTS:S/$/&_s/) $(CSTESTS:S/$/&_s/) $(BTESTS:S/$/&_s/)
|
||||
rm -f *.d
|
||||
rm -f *.o
|
||||
|
28
lib/libpthread/test/README
Normal file
28
lib/libpthread/test/README
Normal file
@ -0,0 +1,28 @@
|
||||
$FreeBSD$
|
||||
|
||||
This test suite is meant to test general functionality of pthreads, as well as
|
||||
provide a simple framework for regression tests. In general, this test suite
|
||||
can be used with any pthreads library, but in reality there are a number of
|
||||
libc_r-specific aspects to this test suite which would require some effort to
|
||||
get around if testing another pthreads library.
|
||||
|
||||
This test suite assumes that libc_r is installed.
|
||||
|
||||
There are two forms of test that the 'verify' script understands. The simpler
|
||||
form is the diff format, where the output of the test program is diff'ed with
|
||||
the correspondingly named .exp file. If there is diff output, the test fails.
|
||||
The sequence test format is somewhat more complex, and is documented in the
|
||||
command line usage output for verify. The advantage of this format is that it
|
||||
allows multiple tests to pass/fail within one program.
|
||||
|
||||
There is no driving need for test naming consistency, but the existing tests
|
||||
generally follow these conventions:
|
||||
|
||||
<name>_d.c <name>_d.exp : Diff mode C test and expected output file.
|
||||
<name>_s.c : Sequence mode C test.
|
||||
<name>_b*.c : Back end C program used by perl tests.
|
||||
<name>_d.pl <name>_d.pl.exp : Diff mode perl test and expected output file.
|
||||
<name>_s.pl : Sequence mode perl test.
|
||||
|
||||
<name> is something descriptive, such as "pr14685" in the case of a PR-related
|
||||
regression test, or "mutex" in the case of a test of mutexes.
|
13
lib/libpthread/test/hello_b.c
Normal file
13
lib/libpthread/test/hello_b.c
Normal file
@ -0,0 +1,13 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Back end C programs can be anything compilable.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
return 0;
|
||||
}
|
38
lib/libpthread/test/hello_d.c
Normal file
38
lib/libpthread/test/hello_d.c
Normal file
@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple diff mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
return 0;
|
||||
}
|
1
lib/libpthread/test/hello_d.exp
Normal file
1
lib/libpthread/test/hello_d.exp
Normal file
@ -0,0 +1 @@
|
||||
Hello world
|
47
lib/libpthread/test/hello_s.c
Normal file
47
lib/libpthread/test/hello_s.c
Normal file
@ -0,0 +1,47 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Simple sequence mode test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
fprintf(stderr, "ok 1\n");
|
||||
fprintf(stderr, "ok \n");
|
||||
fprintf(stderr, "ok 3\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t thread;
|
||||
int error;
|
||||
|
||||
fprintf(stderr, "1..3\n");
|
||||
|
||||
fprintf(stderr, "Some random text\n");
|
||||
|
||||
error = pthread_create(&thread, NULL, entry, NULL);
|
||||
fprintf(stderr, "More unimportant text\n");
|
||||
if (error)
|
||||
fprintf(stderr,"Error in pthread_create(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
error = pthread_join(thread, NULL);
|
||||
if (error)
|
||||
fprintf(stderr, "Error in pthread_join(): %s\n",
|
||||
strerror(error));
|
||||
|
||||
fprintf(stderr, "Hello world\n");
|
||||
|
||||
return 0;
|
||||
}
|
1549
lib/libpthread/test/mutex_d.c
Normal file
1549
lib/libpthread/test/mutex_d.c
Normal file
File diff suppressed because it is too large
Load Diff
290
lib/libpthread/test/mutex_d.exp
Normal file
290
lib/libpthread/test/mutex_d.exp
Normal file
@ -0,0 +1,290 @@
|
||||
|
||||
Testing pthread_mutex_init
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified) - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE - PASS
|
||||
|
||||
Testing pthread_mutex_destroy
|
||||
-----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Destruction of unused mutex - PASS
|
||||
Destruction of mutex locked by self - PASS
|
||||
Destruction of mutex locked by another thread - PASS
|
||||
Destruction of mutex while being used in cond_wait - PASS
|
||||
|
||||
Testing pthread_mutex_lock
|
||||
--------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock on unlocked mutex - PASS
|
||||
Lock on invalid mutex - PASS
|
||||
Lock on mutex held by self - PASS
|
||||
|
||||
Testing pthread_mutex_unlock
|
||||
----------------------------
|
||||
Protocol PTHREAD_PRIO_NONE, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_NONE, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
Protocol PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Unlock on mutex held by self - PASS
|
||||
Unlock on invalid mutex - PASS
|
||||
Unlock on mutex locked by another thread - PASS
|
||||
|
||||
Testing queueing order
|
||||
----------------------
|
||||
Queueing order on a mutex - PASS
|
||||
Queueing order on a condition variable - PASS
|
||||
|
||||
Testing priority inheritence
|
||||
----------------------------
|
||||
Protype PTHREAD_PRIO_INHERIT, Type POSIX (type not specified)
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
Protype PTHREAD_PRIO_INHERIT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Simple inheritence test - PASS
|
||||
Inheritence test with change of priority - PASS
|
||||
|
||||
Testing priority ceilings
|
||||
-------------------------
|
||||
Protype PTHREAD_PRIO_PROTECT, Type POSIX (type not specified)
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_DEFAULT
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_ERRORCHECK
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_NORMAL
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
Protype PTHREAD_PRIO_PROTECT, Type SS2 PTHREAD_MUTEX_RECURSIVE
|
||||
Lock with ceiling priority < thread priority - PASS
|
||||
Lock with ceiling priority = thread priority - PASS
|
||||
Lock with ceiling priority > thread priority - PASS
|
||||
Preemption with ceiling priority < thread priority - PASS
|
||||
Preemption with ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority = thread priority - PASS
|
||||
SCHED_FIFO scheduling and ceiling priority > thread priority - PASS
|
||||
|
||||
Total tests 212, passed 212, failed 0
|
135
lib/libpthread/test/sem_d.c
Normal file
135
lib/libpthread/test/sem_d.c
Normal file
@ -0,0 +1,135 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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(s), this list of conditions and the following disclaimer as
|
||||
* the first lines of this file unmodified other than the possible
|
||||
* addition of one or more copyright notices.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
*
|
||||
****************************************************************************
|
||||
*
|
||||
* sem test.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#define _REENTRANT
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define NTHREADS 10
|
||||
|
||||
void *
|
||||
entry(void * a_arg)
|
||||
{
|
||||
sem_t * sem = (sem_t *) a_arg;
|
||||
|
||||
sem_wait(sem);
|
||||
fprintf(stderr, "Got semaphore\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
sem_t sem_a, sem_b;
|
||||
pthread_t threads[NTHREADS];
|
||||
unsigned i;
|
||||
int val;
|
||||
|
||||
fprintf(stderr, "Test begin\n");
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(-1 == sem_init(&sem_b, 1, 0));
|
||||
assert(EPERM == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_init(&sem_b, 0, 0));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(0 == val);
|
||||
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_getvalue(&sem_b, &val));
|
||||
assert(1 == val);
|
||||
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(-1 == sem_trywait(&sem_b));
|
||||
assert(EAGAIN == errno);
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_trywait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
assert(0 == sem_wait(&sem_b));
|
||||
assert(0 == sem_post(&sem_b));
|
||||
|
||||
#ifdef _LIBC_R_
|
||||
assert(SEM_FAILED == sem_open("/foo", O_CREAT | O_EXCL, 0644, 0));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_close(&sem_b));
|
||||
assert(ENOSYS == errno);
|
||||
|
||||
assert(-1 == sem_unlink("/foo"));
|
||||
assert(ENOSYS == errno);
|
||||
#endif
|
||||
|
||||
assert(0 == sem_destroy(&sem_b));
|
||||
|
||||
assert(0 == sem_init(&sem_a, 0, 0));
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_create(&threads[i], NULL, entry, (void *) &sem_a);
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
assert(0 == sem_post(&sem_a));
|
||||
}
|
||||
|
||||
for (i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
|
||||
assert(0 == sem_destroy(&sem_a));
|
||||
|
||||
fprintf(stderr, "Test end\n");
|
||||
return 0;
|
||||
}
|
22
lib/libpthread/test/sem_d.exp
Normal file
22
lib/libpthread/test/sem_d.exp
Normal file
@ -0,0 +1,22 @@
|
||||
Test begin
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Got semaphore
|
||||
Test end
|
288
lib/libpthread/test/sigsuspend_d.c
Normal file
288
lib/libpthread/test/sigsuspend_d.c
Normal file
@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Daniel M. Eischen.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
static int sigcounts[NSIG + 1];
|
||||
static int sigfifo[NSIG + 1];
|
||||
static int fifo_depth = 0;
|
||||
static sigset_t suspender_mask;
|
||||
static pthread_t suspender_tid;
|
||||
|
||||
|
||||
static void *
|
||||
sigsuspender (void *arg)
|
||||
{
|
||||
int save_count, status, i;
|
||||
sigset_t run_mask;
|
||||
|
||||
/* Run with all signals blocked. */
|
||||
sigfillset (&run_mask);
|
||||
sigprocmask (SIG_SETMASK, &run_mask, NULL);
|
||||
|
||||
/* Allow these signals to wake us up during a sigsuspend. */
|
||||
sigfillset (&suspender_mask); /* Default action */
|
||||
sigdelset (&suspender_mask, SIGINT); /* terminate */
|
||||
sigdelset (&suspender_mask, SIGHUP); /* terminate */
|
||||
sigdelset (&suspender_mask, SIGQUIT); /* create core image */
|
||||
sigdelset (&suspender_mask, SIGURG); /* ignore */
|
||||
sigdelset (&suspender_mask, SIGIO); /* ignore */
|
||||
sigdelset (&suspender_mask, SIGUSR2); /* terminate */
|
||||
|
||||
while (sigcounts[SIGINT] == 0) {
|
||||
save_count = sigcounts[SIGUSR2];
|
||||
|
||||
status = sigsuspend (&suspender_mask);
|
||||
if ((status == 0) || (errno != EINTR)) {
|
||||
fprintf (stderr, "Unable to suspend for signals, "
|
||||
"errno %d, return value %d\n",
|
||||
errno, status);
|
||||
exit (1);
|
||||
}
|
||||
for (i = 0; i < fifo_depth; i++)
|
||||
fprintf (stderr, "Sigsuspend woke up by signal %d\n",
|
||||
sigfifo[i]);
|
||||
fifo_depth = 0;
|
||||
}
|
||||
|
||||
pthread_exit (arg);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sighandler (int signo)
|
||||
{
|
||||
sigset_t set, suspend_set;
|
||||
pthread_t self;
|
||||
|
||||
if ((signo >= 0) && (signo <= NSIG))
|
||||
sigcounts[signo]++;
|
||||
|
||||
/*
|
||||
* If we are running on behalf of the suspender thread,
|
||||
* ensure that we have the correct mask set.
|
||||
*/
|
||||
self = pthread_self ();
|
||||
if (self == suspender_tid) {
|
||||
sigfifo[fifo_depth] = signo;
|
||||
fifo_depth++;
|
||||
fprintf (stderr,
|
||||
" -> Suspender thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
|
||||
/* Get the current signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &set);
|
||||
|
||||
/* The handler should run with the current signal masked. */
|
||||
suspend_set = suspender_mask;
|
||||
sigaddset(&suspend_set, signo);
|
||||
|
||||
if (memcmp(&set, &suspend_set, sizeof(set)))
|
||||
fprintf (stderr,
|
||||
" >>> FAIL: sigsuspender signal handler running "
|
||||
"with incorrect mask.\n");
|
||||
}
|
||||
else
|
||||
fprintf (stderr,
|
||||
" -> Main thread signal handler caught signal %d\n",
|
||||
signo);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
pthread_attr_t pattr;
|
||||
void * exit_status;
|
||||
struct sigaction act;
|
||||
sigset_t oldset;
|
||||
sigset_t newset;
|
||||
|
||||
/* Initialize our signal counts. */
|
||||
memset ((void *) sigcounts, 0, NSIG * sizeof (int));
|
||||
|
||||
/* Ignore signal SIGIO. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGIO);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGIO, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGURG. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGURG);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGURG, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGXCPU */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGXCPU);
|
||||
sigaction (SIGXCPU, &act, NULL);
|
||||
|
||||
/* Get our current signal mask. */
|
||||
sigprocmask (SIG_SETMASK, NULL, &oldset);
|
||||
|
||||
/* Mask out SIGUSR1 and SIGUSR2. */
|
||||
newset = oldset;
|
||||
sigaddset (&newset, SIGUSR1);
|
||||
sigaddset (&newset, SIGUSR2);
|
||||
sigprocmask (SIG_SETMASK, &newset, NULL);
|
||||
|
||||
/* Install a signal handler for SIGUSR1 */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGUSR1);
|
||||
sigaction (SIGUSR1, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGUSR2 */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGUSR2);
|
||||
sigaction (SIGUSR2, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize the thread attribute.
|
||||
*/
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the sigsuspender thread.
|
||||
*/
|
||||
if (pthread_create (&suspender_tid, &pattr, sigsuspender, NULL) != 0) {
|
||||
fprintf (stderr, "Unable to create thread, errno %d.\n", errno);
|
||||
exit (1);
|
||||
}
|
||||
#if defined(_LIBC_R)
|
||||
pthread_set_name_np (suspender_tid, "sigsuspender");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify that an ignored signal doesn't cause a wakeup.
|
||||
* We don't have a handler installed for SIGIO.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGIO);
|
||||
sleep (1);
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
fprintf (stderr, "FAIL: sigsuspend wakes up for ignored signal "
|
||||
"SIGIO.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action of ignore, for
|
||||
* which we have a signal handler installed, will release a
|
||||
* sigsuspend.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGURG);
|
||||
sleep (1);
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a SIGUSR2 signal will release a sigsuspended
|
||||
* thread.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGUSR2);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR2);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR2] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigsuspend doesn't wake up for SIGUSR2.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal, blocked in both the main and
|
||||
* sigsuspender threads, does not cause the signal handler
|
||||
* to be called.
|
||||
*/
|
||||
send_thread_signal (suspender_tid, SIGUSR1);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 0)
|
||||
fprintf (stderr, "FAIL: signal hander called for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
||||
*/
|
||||
pthread_join (suspender_tid, &exit_status);
|
||||
|
||||
return (0);
|
||||
}
|
8
lib/libpthread/test/sigsuspend_d.exp
Normal file
8
lib/libpthread/test/sigsuspend_d.exp
Normal file
@ -0,0 +1,8 @@
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 16
|
||||
Sigsuspend woke up by signal 16
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
||||
-> Suspender thread signal handler caught signal 31
|
||||
Sigsuspend woke up by signal 31
|
304
lib/libpthread/test/sigwait_d.c
Normal file
304
lib/libpthread/test/sigwait_d.c
Normal file
@ -0,0 +1,304 @@
|
||||
/*
|
||||
* Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Daniel M. Eischen.
|
||||
* 4. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN 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 REGENTS 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_LIBC_R_)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
static int sigcounts[NSIG + 1];
|
||||
static sigset_t wait_mask;
|
||||
static pthread_mutex_t waiter_mutex;
|
||||
|
||||
|
||||
static void *
|
||||
sigwaiter (void *arg)
|
||||
{
|
||||
int signo;
|
||||
sigset_t mask;
|
||||
|
||||
/* Block SIGHUP */
|
||||
sigemptyset (&mask);
|
||||
sigaddset (&mask, SIGHUP);
|
||||
sigprocmask (SIG_BLOCK, &mask, NULL);
|
||||
|
||||
while (sigcounts[SIGINT] == 0) {
|
||||
if (sigwait (&wait_mask, &signo) != 0) {
|
||||
fprintf (stderr,
|
||||
"Unable to wait for signal, errno %d\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
sigcounts[signo]++;
|
||||
fprintf (stderr, "Sigwait caught signal %d\n", signo);
|
||||
|
||||
/* Allow the main thread to prevent the sigwait. */
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
}
|
||||
|
||||
pthread_exit (arg);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sighandler (int signo)
|
||||
{
|
||||
fprintf (stderr, " -> Signal handler caught signal %d\n", signo);
|
||||
|
||||
if ((signo >= 0) && (signo <= NSIG))
|
||||
sigcounts[signo]++;
|
||||
}
|
||||
|
||||
static void
|
||||
send_thread_signal (pthread_t tid, int signo)
|
||||
{
|
||||
if (pthread_kill (tid, signo) != 0) {
|
||||
fprintf (stderr, "Unable to send thread signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
send_process_signal (int signo)
|
||||
{
|
||||
if (kill (getpid (), signo) != 0) {
|
||||
fprintf (stderr, "Unable to send process signal, errno %d.\n",
|
||||
errno);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
pthread_mutexattr_t mattr;
|
||||
pthread_attr_t pattr;
|
||||
pthread_t tid;
|
||||
void * exit_status;
|
||||
struct sigaction act;
|
||||
|
||||
/* Initialize our signal counts. */
|
||||
memset ((void *) sigcounts, 0, NSIG * sizeof (int));
|
||||
|
||||
/* Setup our wait mask. */
|
||||
sigemptyset (&wait_mask); /* Default action */
|
||||
sigaddset (&wait_mask, SIGHUP); /* terminate */
|
||||
sigaddset (&wait_mask, SIGINT); /* terminate */
|
||||
sigaddset (&wait_mask, SIGQUIT); /* create core image */
|
||||
sigaddset (&wait_mask, SIGURG); /* ignore */
|
||||
sigaddset (&wait_mask, SIGIO); /* ignore */
|
||||
sigaddset (&wait_mask, SIGUSR1); /* terminate */
|
||||
|
||||
/* Ignore signals SIGHUP and SIGIO. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGHUP);
|
||||
sigaddset (&act.sa_mask, SIGIO);
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
sigaction (SIGHUP, &act, NULL);
|
||||
sigaction (SIGIO, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGURG */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGURG);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGURG, &act, NULL);
|
||||
|
||||
/* Install a signal handler for SIGXCPU */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGXCPU);
|
||||
sigaction (SIGXCPU, &act, NULL);
|
||||
|
||||
/*
|
||||
* Initialize the thread attribute.
|
||||
*/
|
||||
if ((pthread_attr_init (&pattr) != 0) ||
|
||||
(pthread_attr_setdetachstate (&pattr,
|
||||
PTHREAD_CREATE_JOINABLE) != 0)) {
|
||||
fprintf (stderr, "Unable to initialize thread attributes.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and create a mutex.
|
||||
*/
|
||||
if ((pthread_mutexattr_init (&mattr) != 0) ||
|
||||
(pthread_mutex_init (&waiter_mutex, &mattr) != 0)) {
|
||||
fprintf (stderr, "Unable to create waiter mutex.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the sigwaiter thread.
|
||||
*/
|
||||
if (pthread_create (&tid, &pattr, sigwaiter, NULL) != 0) {
|
||||
fprintf (stderr, "Unable to create thread.\n");
|
||||
exit (1);
|
||||
}
|
||||
#if defined(_LIBC_R_)
|
||||
pthread_set_name_np (tid, "sigwaiter");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify that an ignored signal doesn't cause a wakeup.
|
||||
* We don't have a handler installed for SIGIO.
|
||||
*/
|
||||
send_thread_signal (tid, SIGIO);
|
||||
sleep (1);
|
||||
send_process_signal (SIGIO);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGIO] != 0)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait wakes up for ignored signal SIGIO.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action of ignore, for
|
||||
* which we have a signal handler installed, will release a sigwait.
|
||||
*/
|
||||
send_thread_signal (tid, SIGURG);
|
||||
sleep (1);
|
||||
send_process_signal (SIGURG);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGURG] != 2)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGURG.\n");
|
||||
|
||||
/*
|
||||
* Verify that a signal with a default action that terminates
|
||||
* the process will release a sigwait.
|
||||
*/
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
sleep (1);
|
||||
send_process_signal (SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that if we install a signal handler for a previously
|
||||
* ignored signal, an occurrence of this signal will release
|
||||
* the (already waiting) sigwait.
|
||||
*/
|
||||
|
||||
/* Install a signal handler for SIGHUP. */
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigaddset (&act.sa_mask, SIGHUP);
|
||||
act.sa_handler = sighandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
sigaction (SIGHUP, &act, NULL);
|
||||
|
||||
/* Sending SIGHUP should release the sigwait. */
|
||||
send_process_signal (SIGHUP);
|
||||
sleep (1);
|
||||
send_thread_signal (tid, SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Verify that a pending signal in the waiters mask will
|
||||
* cause sigwait to return the pending signal. We do this
|
||||
* by taking the waiters mutex and signaling the waiter to
|
||||
* release him from the sigwait. The waiter will block
|
||||
* on taking the mutex, and we can then send the waiter a
|
||||
* signal which should be added to his pending signals.
|
||||
* The next time the waiter does a sigwait, he should
|
||||
* return with the pending signal.
|
||||
*/
|
||||
sigcounts[SIGHUP] = 0;
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
/* Release the waiter from sigwait. */
|
||||
send_process_signal (SIGHUP);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 1)
|
||||
fprintf (stderr, "FAIL: sigwait doesn't wake up for SIGHUP.\n");
|
||||
/*
|
||||
* Add SIGHUP to the process pending signals. Since there is
|
||||
* a signal handler installed for SIGHUP and this signal is
|
||||
* blocked from the waiter thread and unblocked in the main
|
||||
* thread, the signal handler should be called once for SIGHUP.
|
||||
*/
|
||||
send_process_signal (SIGHUP);
|
||||
/* Release the waiter thread and allow him to run. */
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGHUP] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGHUP.\n");
|
||||
|
||||
/*
|
||||
* Repeat the above test using pthread_kill and SIGUSR1.
|
||||
*/
|
||||
sigcounts[SIGUSR1] = 0;
|
||||
pthread_mutex_lock (&waiter_mutex);
|
||||
/* Release the waiter from sigwait. */
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 1)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't wake up for SIGUSR1.\n");
|
||||
/* Add SIGHUP to the waiters pending signals. */
|
||||
send_thread_signal (tid, SIGUSR1);
|
||||
/* Release the waiter thread and allow him to run. */
|
||||
pthread_mutex_unlock (&waiter_mutex);
|
||||
sleep (1);
|
||||
if (sigcounts[SIGUSR1] != 2)
|
||||
fprintf (stderr,
|
||||
"FAIL: sigwait doesn't return for pending SIGUSR1.\n");
|
||||
|
||||
/*
|
||||
* Verify that we can still kill the process for a signal
|
||||
* not being waited on by sigwait.
|
||||
*/
|
||||
send_process_signal (SIGPIPE);
|
||||
fprintf (stderr, "FAIL: SIGPIPE did not terminate process.\n");
|
||||
|
||||
/*
|
||||
* Wait for the thread to finish.
|
||||
*/
|
||||
pthread_join (tid, &exit_status);
|
||||
|
||||
return (0);
|
||||
}
|
10
lib/libpthread/test/sigwait_d.exp
Normal file
10
lib/libpthread/test/sigwait_d.exp
Normal file
@ -0,0 +1,10 @@
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 16
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
Sigwait caught signal 1
|
||||
-> Signal handler caught signal 1
|
||||
Sigwait caught signal 30
|
||||
Sigwait caught signal 30
|
505
lib/libpthread/test/verify
Executable file
505
lib/libpthread/test/verify
Executable file
@ -0,0 +1,505 @@
|
||||
#!/usr/bin/perl -w
|
||||
#-*-mode:perl-*-
|
||||
#############################################################################
|
||||
#
|
||||
# Copyright (C) 1999-2000 Jason Evans <jasone@freebsd.org>.
|
||||
# All rights reserved.
|
||||
#
|
||||
# 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(s), this list of conditions and the following disclaimer as
|
||||
# the first lines of this file unmodified other than the possible
|
||||
# addition of one or more copyright notices.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice(s), 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 HOLDER(S) ``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 HOLDER(S) 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.
|
||||
#
|
||||
#############################################################################
|
||||
#
|
||||
# Test harness.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
# Shut off buffering.
|
||||
select(STDOUT);
|
||||
$| = 1;
|
||||
|
||||
#
|
||||
# Parse command-line arguments.
|
||||
#
|
||||
use Getopt::Long;
|
||||
Getopt::Long::config("bundling"); # Allow -hv rather than forcing -h -v.
|
||||
|
||||
# Set option defaults for optional arguments.
|
||||
$opt_help = 0;
|
||||
$opt_verbose = 0;
|
||||
$opt_quiet = 0;
|
||||
$opt_srcdir = ".";
|
||||
$opt_ustats = 0;
|
||||
$opt_zero = 0;
|
||||
|
||||
$opt_retval =
|
||||
&GetOptions("h|help" => \$opt_help,
|
||||
"v|verbose" => \$opt_verbose,
|
||||
"q|quiet" => \$opt_quiet,
|
||||
"s|srcdir=s" => \$opt_srcdir,
|
||||
"u|ustats" => \$opt_ustats,
|
||||
"z|zero" => \$opt_zero
|
||||
);
|
||||
|
||||
$mode = "d";
|
||||
for ($i = 0; $i <= $#ARGV; $i++)
|
||||
{
|
||||
if (($ARGV[$i] eq "-s") || ($ARGV[$i] eq "--sequence"))
|
||||
{
|
||||
$mode = "s";
|
||||
}
|
||||
elsif (($ARGV[$i] eq "-d") || ($ARGV[$i] eq "--diff"))
|
||||
{
|
||||
$mode = "d";
|
||||
}
|
||||
elsif (-x $ARGV[$i])
|
||||
{
|
||||
if ($mode eq "s")
|
||||
{
|
||||
@STESTS = (@STESTS, $ARGV[$i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@DTESTS = (@DTESTS, $ARGV[$i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot run \"$ARGV[$i]\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt_help)
|
||||
{
|
||||
&usage();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if ($opt_retval == 0)
|
||||
{
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose && $opt_quiet)
|
||||
{
|
||||
print STDERR "-v and -q are incompatible\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($#STESTS + $#DTESTS + 2 == 0)
|
||||
{
|
||||
print STDERR "No tests specified\n";
|
||||
&usage();
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Option values: h:$opt_help, v:$opt_verbose, q:$opt_quiet, "
|
||||
. "u:$opt_ustats\n";
|
||||
printf STDERR "Sequence tests (%d total): @STESTS\n", $#STESTS + 1;
|
||||
printf STDERR "Diff tests (%d total): @DTESTS\n", $#DTESTS + 1;
|
||||
}
|
||||
|
||||
#
|
||||
# Create and print header.
|
||||
#
|
||||
@TSTATS =
|
||||
(
|
||||
"--------------------------------------------------------------------------\n",
|
||||
"Test c_user c_system c_total chng\n",
|
||||
" passed/FAILED h_user h_system h_total %% chng\n"
|
||||
);
|
||||
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# Run sequence test(s).
|
||||
#
|
||||
$total_utime = 0.0; # Total user time.
|
||||
$total_stime = 0.0; # Total system time.
|
||||
$total_hutime = 0.0; # Total historical user time.
|
||||
$total_hstime = 0.0; # Total historical system time.
|
||||
$total_ntime = 0.0; # Total time for tests that have historical data.
|
||||
|
||||
foreach $test (@STESTS)
|
||||
{
|
||||
# sequence mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (open (STEST_OUT, "<./$test.out"))
|
||||
{
|
||||
$num_failed_subtests = 0;
|
||||
|
||||
$_ = <STEST_OUT>;
|
||||
|
||||
if ($_ =~ /1\.\.(\d+)/)
|
||||
{
|
||||
$num_subtests = $1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$num_subtests = 0;
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "Malformed 1..n line: \"$_\"\n";
|
||||
}
|
||||
}
|
||||
for ($subtest = 1; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
while (defined($line = <STEST_OUT>))
|
||||
{
|
||||
if ($line =~ /^not\s+ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 1;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
elsif ($line =~ /^ok\s+(\d+)?/)
|
||||
{
|
||||
$not = 0;
|
||||
$test_num = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (defined($line))
|
||||
{
|
||||
if (defined($test_num) && ($test_num != $subtest))
|
||||
{
|
||||
# There was no output printed for one or more tests.
|
||||
for (; $subtest < $test_num; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
if ($not)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; $subtest <= $num_subtests; $subtest++)
|
||||
{
|
||||
$num_failed_subtests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < $num_failed_subtests)
|
||||
{
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Cannot open output file \"$test.out\"\n";
|
||||
}
|
||||
exit 1;
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay,
|
||||
$num_failed_subtests, $num_subtests,
|
||||
$utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
foreach $test (@DTESTS)
|
||||
{
|
||||
# Diff mode.
|
||||
$okay = 1;
|
||||
|
||||
($okay, $utime, $stime) = &run_test($test);
|
||||
|
||||
if (-e "./$test.out" && -e "$opt_srcdir/$test.exp")
|
||||
{
|
||||
`diff ./$test.out $opt_srcdir/$test.exp > ./$test.diff 2>&1`;
|
||||
if ($?)
|
||||
{
|
||||
# diff returns non-zero if there is a difference.
|
||||
$okay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR
|
||||
"Nonexistent expected output file \"$opt_srcdir/$test.exp\"\n";
|
||||
print STDERR "\$opt_srcdir is \"$opt_srcdir\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
($hutime, $hstime) = &print_stats($test, $okay, 0, 0, $utime, $stime);
|
||||
$total_hutime += $hutime;
|
||||
$total_hstime += $hstime;
|
||||
|
||||
if ($okay)
|
||||
{
|
||||
$total_utime += $utime;
|
||||
$total_stime += $stime;
|
||||
}
|
||||
else
|
||||
{
|
||||
@FAILED_TESTS = (@FAILED_TESTS, $test);
|
||||
}
|
||||
|
||||
# If there were historical data, add the run time to the total time to
|
||||
# compare against the historical run time.
|
||||
if (0 < ($hutime + $hstime))
|
||||
{
|
||||
$total_ntime += $utime + $stime;
|
||||
}
|
||||
}
|
||||
|
||||
# Print summary stats.
|
||||
$tt_str = sprintf ("%d / %d passed (%5.2f%%%%)",
|
||||
($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1),
|
||||
$#STESTS + $#DTESTS + 2,
|
||||
(($#STESTS + $#DTESTS + 2) - ($#FAILED_TESTS + 1))
|
||||
/ ($#STESTS + $#DTESTS + 2) * 100);
|
||||
|
||||
$t_str = sprintf ("Totals %7.2f %7.2f %7.2f"
|
||||
. " %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$total_utime, $total_stime, $total_utime + $total_stime,
|
||||
($total_ntime - ($total_hutime + $total_hstime)),
|
||||
$tt_str . ' ' x (40 - length($tt_str)),
|
||||
$total_hutime, $total_hstime, $total_hutime + $total_hstime,
|
||||
($total_hutime + $total_hstime == 0.0) ? 0.0 :
|
||||
(($total_ntime
|
||||
- ($total_hutime + $total_hstime))
|
||||
/ ($total_hutime + $total_hstime) * 100));
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n",
|
||||
$t_str,
|
||||
"--------------------------------------------------------------------------\n"
|
||||
);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
# End of main execution.
|
||||
|
||||
sub run_test
|
||||
{
|
||||
my ($test) = @_;
|
||||
my ($okay) = 1;
|
||||
my ($tutime, $tstime);
|
||||
my ($utime, $stime, $cutime, $cstime);
|
||||
my (@TSTATS);
|
||||
my ($t_str);
|
||||
|
||||
@TSTATS = ("--------------------------------------------------------------------------\n");
|
||||
|
||||
$t_str = sprintf ("%s%s", $test, ' ' x (40 - length($test)));
|
||||
@TSTATS = (@TSTATS, $t_str);
|
||||
@STATS = (@STATS, @TSTATS);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
($utime, $stime, $cutime, $cstime) = times;
|
||||
`./$test $opt_srcdir > ./$test.out 2>&1`;
|
||||
($utime, $stime, $tutime, $tstime) = times;
|
||||
|
||||
# Subtract the before time from the after time.
|
||||
$tutime -= $cutime;
|
||||
$tstime -= $cstime;
|
||||
|
||||
if ($opt_zero)
|
||||
{
|
||||
if ($?)
|
||||
{
|
||||
$okay = 0;
|
||||
if ($opt_verbose)
|
||||
{
|
||||
print STDERR "\"./$test > ./$test.out 2>&1\" returned $?\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ($okay, $tutime, $tstime);
|
||||
}
|
||||
|
||||
sub print_stats
|
||||
{
|
||||
my ($test, $okay, $failed_subtests, $subtests, $utime, $stime) = @_;
|
||||
my ($hutime, $hstime);
|
||||
# my (TEST_PERF);
|
||||
my (@TSTATS);
|
||||
my ($t_str, $pass_str);
|
||||
|
||||
$pass_str = $okay ? "passed" : "*** FAILED ***";
|
||||
if ((0 != $subtests) && (!$okay))
|
||||
{
|
||||
$pass_str = $pass_str . " ($failed_subtests/$subtests failed)";
|
||||
}
|
||||
$pass_str = $pass_str . ' ' x (39 - length($pass_str));
|
||||
|
||||
if (-r "$test.perf")
|
||||
{
|
||||
if (!open (TEST_PERF, "<./$test.perf"))
|
||||
{
|
||||
print STDERR "Unable to open \"./$test.perf\"\n";
|
||||
exit 1;
|
||||
}
|
||||
$_ = <TEST_PERF>;
|
||||
|
||||
($hutime, $hstime) = split;
|
||||
close TEST_PERF;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f %7.2f\n"
|
||||
. " %s %7.2f %7.2f %7.2f %7.2f%%%%\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
($utime + $stime) - ($hutime + $hstime),
|
||||
$pass_str,
|
||||
$hutime, $hstime, $hutime + $hstime,
|
||||
(($hutime + $hstime) == 0.0) ? 0.0 :
|
||||
((($utime + $stime) - ($hutime + $hstime))
|
||||
/ ($hutime + $hstime) * 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
$hutime = 0.0;
|
||||
$hstime = 0.0;
|
||||
|
||||
$t_str = sprintf (" %7.2f %7.2f %7.2f \n"
|
||||
. " %s\n",
|
||||
$utime, $stime, $utime + $stime,
|
||||
$pass_str);
|
||||
}
|
||||
@TSTATS = ($t_str);
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
foreach $line (@TSTATS)
|
||||
{
|
||||
printf STDOUT "$line";
|
||||
}
|
||||
}
|
||||
|
||||
if ($okay && $opt_ustats)
|
||||
{
|
||||
if (!open (TEST_PERF, ">./$test.perf"))
|
||||
{
|
||||
if (!$opt_quiet)
|
||||
{
|
||||
print STDERR "Unable to update \"$test.perf\"\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print TEST_PERF "$utime $stime\n";
|
||||
close TEST_PERF;
|
||||
}
|
||||
}
|
||||
|
||||
return ($hutime, $hstime);
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
print <<EOF;
|
||||
$0 usage:
|
||||
$0 [<options>] -- {[-s | -d | --sequence | --diff] <test>+}+
|
||||
|
||||
Option | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-h --help | Print usage and exit.
|
||||
-v --verbose | Verbose (incompatible with quiet).
|
||||
-q --quiet | Quiet (incompatible with verbose).
|
||||
-s --srcdir | Path to source tree (default is ".").
|
||||
-u --ustats | Update historical statistics (stored in "<test>.perf".
|
||||
-z --zero | Consider non-zero exit code to be an error.
|
||||
--------------+-------------------------------------------------------------
|
||||
|
||||
Flag | Description
|
||||
--------------+-------------------------------------------------------------
|
||||
-s --sequence | Sequence mode (default).
|
||||
| Output to stdout of the following form is expected:
|
||||
|
|
||||
| -----------------
|
||||
| 1..<n>
|
||||
| {not} ok [1]
|
||||
| {not} ok [2]
|
||||
| ...
|
||||
| {not} ok [n]
|
||||
| -----------------
|
||||
|
|
||||
| 1 <= <n> < 2^31
|
||||
|
|
||||
| Lines which do not match the patterns shown above are
|
||||
| ignored, except that the 1..<n> construct must be the first
|
||||
| line of output seen.
|
||||
|
|
||||
-d --diff | Diff mode (incompatible with sequence mode).
|
||||
| If <test>.exp exists, diff it with the output from <test> to
|
||||
| determine success or failure.
|
||||
--------------+-------------------------------------------------------------
|
||||
EOF
|
||||
}
|
Loading…
Reference in New Issue
Block a user