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:
jasone 2000-04-24 21:07:45 +00:00
parent c30aa3de8d
commit 85d4e50332
48 changed files with 7983 additions and 75 deletions

View File

@ -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
View 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
View 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
View 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;
}

View File

@ -0,0 +1 @@
Hello world

47
lib/libc_r/test/hello_s.c Normal file
View 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;
}

View File

@ -1,8 +0,0 @@
# $FreeBSD$
PROG= mutex
SRCS= mutex.c
NOMAN= 1
LDFLAGS= -pthread
.include <bsd.prog.mk>

View File

@ -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,
&param) == 0);
#if defined(__FreeBSD__)
#if defined(_LIBC_R_)
{
char buf[30];

290
lib/libc_r/test/mutex_d.exp Normal file
View 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
View 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
View 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

View File

@ -1,8 +0,0 @@
# $FreeBSD$
PROG= sigsuspend
SRCS= sigsuspend.c
NOMAN= 1
LDFLAGS= -pthread
.include <bsd.prog.mk>

View File

@ -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);
}

View 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

View File

@ -1,8 +0,0 @@
# $FreeBSD$
PROG= sigwait
SRCS= sigwait.c
NOMAN= 1
LDFLAGS= -pthread
.include <bsd.prog.mk>

View File

@ -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.

View 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
View 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
}

View File

@ -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
View 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
View 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
View 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;
}

View File

@ -0,0 +1 @@
Hello world

47
lib/libkse/test/hello_s.c Normal file
View 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

File diff suppressed because it is too large Load Diff

290
lib/libkse/test/mutex_d.exp Normal file
View 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
View 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
View 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

View 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);
}

View 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
View 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);
}

View 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
View 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
}

View File

@ -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

View 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.

View File

@ -0,0 +1,13 @@
/****************************************************************************
*
* Back end C programs can be anything compilable.
*
* $FreeBSD$
*
****************************************************************************/
int
main()
{
return 0;
}

View 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;
}

View File

@ -0,0 +1 @@
Hello world

View 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;
}

File diff suppressed because it is too large Load Diff

View 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
View 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;
}

View 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

View 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);
}

View 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

View 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);
}

View 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
View 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
}