summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/nptl/Makefile.in70
-rw-r--r--test/nptl/tst-align3.c57
-rw-r--r--test/nptl/tst-basic7.c75
-rw-r--r--test/nptl/tst-cancel18.c174
-rw-r--r--test/nptl/tst-cancel23.c1
-rw-r--r--test/nptl/tst-cancel25.c171
-rw-r--r--test/nptl/tst-cancel4.c2374
-rw-r--r--test/nptl/tst-cancel5.c1
-rw-r--r--test/nptl/tst-cancelx10.c1
-rw-r--r--test/nptl/tst-cancelx11.c1
-rw-r--r--test/nptl/tst-cancelx12.c1
-rw-r--r--test/nptl/tst-cancelx13.c1
-rw-r--r--test/nptl/tst-cancelx14.c1
-rw-r--r--test/nptl/tst-cancelx15.c1
-rw-r--r--test/nptl/tst-cancelx16.c1
-rw-r--r--test/nptl/tst-cancelx18.c1
-rw-r--r--test/nptl/tst-cancelx2.c1
-rw-r--r--test/nptl/tst-cancelx20.c1
-rw-r--r--test/nptl/tst-cancelx21.c1
-rw-r--r--test/nptl/tst-cancelx3.c1
-rw-r--r--test/nptl/tst-cancelx4.c1
-rw-r--r--test/nptl/tst-cancelx6.c1
-rw-r--r--test/nptl/tst-cancelx7.c1
-rw-r--r--test/nptl/tst-cancelx8.c1
-rw-r--r--test/nptl/tst-cancelx9.c1
-rw-r--r--test/nptl/tst-cleanupx0.c1
-rw-r--r--test/nptl/tst-cleanupx1.c1
-rw-r--r--test/nptl/tst-cleanupx2.c1
-rw-r--r--test/nptl/tst-cleanupx3.c1
-rw-r--r--test/nptl/tst-cleanupx4.c1
-rw-r--r--test/nptl/tst-cond22.c160
-rw-r--r--test/nptl/tst-cond23.c184
-rw-r--r--test/nptl/tst-dlsym1.c66
-rw-r--r--test/nptl/tst-fini1.c35
-rw-r--r--test/nptl/tst-fini1mod.c72
-rw-r--r--test/nptl/tst-getpid1.c122
-rw-r--r--test/nptl/tst-getpid2.c2
-rw-r--r--test/nptl/tst-getpid3.c114
-rw-r--r--test/nptl/tst-initializers1-c89.c1
-rw-r--r--test/nptl/tst-initializers1-c99.c1
-rw-r--r--test/nptl/tst-initializers1-gnu89.c1
-rw-r--r--test/nptl/tst-initializers1-gnu99.c1
-rw-r--r--test/nptl/tst-join6.c2
-rw-r--r--test/nptl/tst-oddstacklimit.c1
-rw-r--r--test/nptl/tst-oncex3.c1
-rw-r--r--test/nptl/tst-oncex4.c1
-rw-r--r--test/nptl/tst-rwlock2a.c2
-rw-r--r--test/nptl/tst-sem10.c88
-rw-r--r--test/nptl/tst-sem11.c76
-rw-r--r--test/nptl/tst-sem12.c14
-rw-r--r--test/nptl/tst-signal7.c59
-rw-r--r--test/nptl/tst-tsd6.c89
-rw-r--r--test/nptl/tst-typesizes.c96
-rw-r--r--test/nptl/tst-unload.c47
-rw-r--r--test/nptl/tst-vfork1.c150
-rw-r--r--test/nptl/tst-vfork1x.c150
-rw-r--r--test/nptl/tst-vfork2.c199
-rw-r--r--test/nptl/tst-vfork2x.c199
58 files changed, 4877 insertions, 1 deletions
diff --git a/test/nptl/Makefile.in b/test/nptl/Makefile.in
index 8ad952a91..b6a279ebf 100644
--- a/test/nptl/Makefile.in
+++ b/test/nptl/Makefile.in
@@ -31,7 +31,19 @@ TESTS := tst-align tst-align2 tst-atfork1 tst-attr1 tst-attr2 tst-attr3 \
tst-signal5 tst-signal6 tst-spin1 tst-spin2 tst-spin3 \
tst-stack1 tst-stack2 tst-stdio1 tst-stdio2 tst-sysconf \
tst-tls1 tst-tls2 tst-tls3 tst-tls4 tst-tls5 tst-tsd1 tst-tsd2 \
- tst-tsd3 tst-tsd4 tst-tsd5 tst-umask1
+ tst-tsd3 tst-tsd4 tst-tsd5 tst-umask1 \
+ tst-align3 tst-cancel4 tst-cancel5 tst-cancel18 tst-cancel23 \
+ tst-cancel25 tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx6 \
+ tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 tst-cancelx11 \
+ tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 tst-cancelx16 \
+ tst-cancelx18 tst-cancelx20 tst-cancelx21 tst-cleanupx0 tst-cleanupx1 \
+ tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 tst-cond22 tst-cond23 \
+ tst-dlsym1 tst-getpid1 tst-getpid2 tst-getpid3 tst-join6 tst-tsd6 \
+ tst-oddstacklimit tst-oncex3 tst-oncex4 tst-rwlock2a \
+ tst-basic7 tst-fini1 tst-signal7 \
+ tst-unload tst-vfork1x tst-vfork2x tst-sem10 tst-sem11 tst-sem12 \
+ tst-typesizes tst-initializers1-c89 tst-initializers1-c99 \
+ tst-initializers1-gnu89 tst-initializers1-gnu99
#
# These are for the RT library and POSIX timers.
@@ -97,9 +109,60 @@ CFLAGS_tst-tls5modd.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
CFLAGS_tst-tls5mode.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
CFLAGS_tst-tls5modf.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-fini1mod.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+LDFLAGS_tst-cond11 = -lrt
+LDFLAGS_tst-cond19 = -lrt
+LDFLAGS_tst-cancel18 = -lrt
+LDFLAGS_tst-cancelx18 = -lrt
+LDFLAGS_tst-clock2 = -lrt
+LDFLAGS_tst-rwlock14 = -lrt
+LDFLAGS_tst-fini1 = -Wl,-rpath=./ tst-fini1mod.so
+LDFLAGS_tst-fini1mod.so = -Wl,-soname=tst-fini1mod.so
+LDFLAGS_tst-unload = -ldl
+LDFLAGS_tst-cancel5 := -lpthread -lpthread_nonshared
+LDFLAGS_tst-cancel23 := -lc -lpthread
+LDFLAGS_tst-vfork1x := -lc -lpthread
+LDFLAGS_tst-vfork2x := -lc -lpthread
+
+CFLAGS_tst-cancelx2 += -fexceptions
+CFLAGS_tst-cancelx3 += -fexceptions
+CFLAGS_tst-cancelx4 += -fexceptions
+CFLAGS_tst-cancelx6 += -fexceptions
+CFLAGS_tst-cancelx7 += -fexceptions
+CFLAGS_tst-cancelx8 += -fexceptions
+CFLAGS_tst-cancelx9 += -fexceptions
+CFLAGS_tst-cancelx10 += -fexceptions
+CFLAGS_tst-cancelx11 += -fexceptions
+CFLAGS_tst-cancelx12 += -fexceptions
+CFLAGS_tst-cancelx13 += -fexceptions
+CFLAGS_tst-cancelx14 += -fexceptions
+CFLAGS_tst-cancelx15 += -fexceptions
+CFLAGS_tst-cancelx16 += -fexceptions
+CFLAGS_tst-cancelx18 += -fexceptions
+CFLAGS_tst-cancelx20 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cancelx21 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx0 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx1 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx2 += -fexceptions
+CFLAGS_tst-cleanupx3 += -fexceptions
+
+CFLAGS_tst-oncex3 += -fexceptions
+CFLAGS_tst-oncex4 += -fexceptions
+CFLAGS_tst-align += $(stack-align-test-flags)
+CFLAGS_tst-align3 += $(stack-align-test-flags)
+CFLAGS_tst-initializers1 = -W -Wall -Werror
+CFLAGS_tst-sem11 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-sem12 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-initializers1 = -W -Wall -Werror
+CFLAGS_tst-initializers1-c89 = $(CFLAGS-tst-initializers1) -std=c89
+CFLAGS_tst-initializers1-c99 = $(CFLAGS-tst-initializers1) -std=c99
+CFLAGS_tst-initializers1-gnu89 = $(CFLAGS-tst-initializers1) -std=gnu89
+CFLAGS_tst-initializers1-gnu99 = $(CFLAGS-tst-initializers1) -std=gnu99
+
EXTRA_LDFLAGS = $(if $(findstring -lpthread,$(LDFLAGS_$@)),,-lpthread)
LDFLAGS_tst-cleanup4 := tst-cleanup4aux.o
+LDFLAGS_tst-cleanupx4 := tst-cleanup4aux.o
LDFLAGS_tst-clock2 := -lrt
LDFLAGS_tst-cond11 := -lrt
LDFLAGS_tst-cond19 := -lrt
@@ -127,6 +190,7 @@ LDFLAGS_tst-timer2 := -lrt -lpthread
LDFLAGS_tst-timer3 := -lrt -lpthread
LDFLAGS_tst-timer4 := -lrt -lpthread
LDFLAGS_tst-timer5 := -lrt -lpthread
+LDFLAGS_tst-dlsym1 := -ldl -rdynamic
LDFLAGS_tst-tls3mod.so := -shared -static-libgcc -lpthread
LDFLAGS_tst-tls4moda.so := -shared -static-libgcc
LDFLAGS_tst-tls4modb.so := -shared -static-libgcc
@@ -137,6 +201,7 @@ LDFLAGS_tst-tls5modc.so := -shared -static-libgcc
LDFLAGS_tst-tls5modd.so := -shared -static-libgcc
LDFLAGS_tst-tls5mode.so := -shared -static-libgcc
LDFLAGS_tst-tls5modf.so := -shared -static-libgcc
+LDFLAGS_tst-cleanupx4 := tst-cleanup4aux.o
#
# Special case
@@ -149,6 +214,9 @@ tst-tls3: tst-tls3mod.so
tst-tls4: tst-tls4moda.so tst-tls4modb.so
tst-tls5: tst-tls5mod.so
+tst-cleanupx4 : tst-cleanup4aux.o
+tst-fini1: tst-fini1mod.so
+
OPTS_tst-cancel7 = --command ./tst-cancel7
OPTS_tst-mqueue7 = -- ./tst-mqueue7
OPTS_tst-exec4 = ./tst-exec4
diff --git a/test/nptl/tst-align3.c b/test/nptl/tst-align3.c
new file mode 100644
index 000000000..f4507f2eb
--- /dev/null
+++ b/test/nptl/tst-align3.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "tst-stack-align.h"
+
+static bool ok = true;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static void
+once_test (void)
+{
+ puts ("in once_test");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+}
+
+static int
+do_test (void)
+{
+ puts ("in main");
+
+ if (TEST_STACK_ALIGN ())
+ ok = false;
+
+ if (pthread_once (&once, once_test))
+ {
+ puts ("pthread once failed");
+ return 1;
+ }
+
+ return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-basic7.c b/test/nptl/tst-basic7.c
new file mode 100644
index 000000000..15b618786
--- /dev/null
+++ b/test/nptl/tst-basic7.c
@@ -0,0 +1,75 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+
+static void use_stack (size_t needed);
+
+void (*use_stack_ptr) (size_t) = use_stack;
+
+static void
+use_stack (size_t needed)
+{
+ size_t sz = sysconf (_SC_PAGESIZE);
+ char *buf = alloca (sz);
+ memset (buf, '\0', sz);
+
+ if (needed > sz)
+ use_stack_ptr (needed - sz);
+}
+
+static void
+use_up_memory (void)
+{
+ struct rlimit rl;
+ getrlimit (RLIMIT_AS, &rl);
+ rl.rlim_cur = 10 * 1024 * 1024;
+ setrlimit (RLIMIT_AS, &rl);
+
+ char *c;
+ int PAGESIZE = getpagesize ();
+ while (1)
+ {
+ c = mmap (NULL, PAGESIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (c == MAP_FAILED)
+ break;
+ }
+}
+
+static void *
+child (void *arg)
+{
+ sleep (1);
+ return arg;
+}
+
+static int
+do_test (void)
+{
+ int err;
+ pthread_t tid;
+
+ /* Allocate the memory needed for the stack. */
+ use_stack_ptr (PTHREAD_STACK_MIN);
+
+ use_up_memory ();
+
+ err = pthread_create (&tid, NULL, child, NULL);
+ if (err != 0)
+ {
+ printf ("pthread_create returns %d: %s\n", err,
+ err == EAGAIN ? "OK" : "FAIL");
+ return err != EAGAIN;
+ }
+
+ /* We did not fail to allocate memory despite the preparation. Oh well. */
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel18.c b/test/nptl/tst-cancel18.c
new file mode 100644
index 000000000..15e9ddfbb
--- /dev/null
+++ b/test/nptl/tst-cancel18.c
@@ -0,0 +1,174 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+/* Cleanup handling test. */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+static void *
+tf (void *arg)
+{
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+ TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
+
+ pthread_cleanup_pop (0);
+
+ puts ("clock_nanosleep returned");
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ puts ("going to cancel in-time");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ return 1;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ puts ("cleanup handler not called");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ puts ("cleanup handler called more than once");
+ return 1;
+ }
+
+ puts ("in-time cancellation succeeded");
+
+
+ cl_called = 0;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+
+ puts ("going to cancel early");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("2nd cancel failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called\n");
+ return 1;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once\n");
+ return 1;
+ }
+
+ puts ("early cancellation succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel23.c b/test/nptl/tst-cancel23.c
new file mode 100644
index 000000000..211168748
--- /dev/null
+++ b/test/nptl/tst-cancel23.c
@@ -0,0 +1 @@
+#include "tst-cancel22.c"
diff --git a/test/nptl/tst-cancel25.c b/test/nptl/tst-cancel25.c
new file mode 100644
index 000000000..00b99ad55
--- /dev/null
+++ b/test/nptl/tst-cancel25.c
@@ -0,0 +1,171 @@
+#include <pthreadP.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b;
+static pthread_t th2;
+
+
+static void *
+tf2 (void *arg)
+{
+ sigset_t mask;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+ if (sigismember (&mask, SIGCANCEL))
+ {
+ puts ("SIGCANCEL blocked in new thread");
+ exit (1);
+ }
+
+ /* Sync with the main thread so that we do not test anything else. */
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ /* Just a cancelable call. */
+ struct timespec ts = { 10000, 0 };
+ nanosleep (&ts, 0);
+ }
+
+ return NULL;
+}
+
+
+static void
+unwhand (void *arg)
+{
+ if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+ {
+ puts ("unwhand: create failed");
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (unwhand, NULL);
+
+ /* Sync with the main thread so that we do not test anything else. */
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ /* Just a cancelable call. */
+ struct timespec ts = { 10000, 0 };
+ nanosleep (&ts, 0);
+ }
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th1;
+ if (pthread_create (&th1, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ /* Make sure tf1 enters nanosleep. */
+ struct timespec ts = { 0, 500000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ ;
+
+ if (pthread_cancel (th1) != 0)
+ {
+ puts ("1st cancel failed");
+ return 1;
+ }
+
+ void *res;
+ if (pthread_join (th1, &res) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ return 1;
+ }
+
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ /* Make sure tf2 enters nanosleep. */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 500000000;
+ while (nanosleep (&ts, &ts) != 0)
+ ;
+
+ puts ("calling pthread_cancel the second time");
+ if (pthread_cancel (th2) != 0)
+ {
+ puts ("2nd cancel failed");
+ return 1;
+ }
+
+ puts ("calling pthread_join the second time");
+ if (pthread_join (th2, &res) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 0;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel4.c b/test/nptl/tst-cancel4.c
new file mode 100644
index 000000000..12d40d5bd
--- /dev/null
+++ b/test/nptl/tst-cancel4.c
@@ -0,0 +1,2374 @@
+/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
+ exit to be called more than once. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/msg.h>
+#include <sys/poll.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include "pthreadP.h"
+
+
+/* Since STREAMS are not supported in the standard Linux kernel and
+ there we don't advertise STREAMS as supported is no need to test
+ the STREAMS related functions. This affects
+ getmsg() getpmsg() putmsg()
+ putpmsg()
+
+ lockf() and fcntl() are tested in tst-cancel16.
+
+ pthread_join() is tested in tst-join5.
+
+ pthread_testcancel()'s only purpose is to allow cancellation. This
+ is tested in several places.
+
+ sem_wait() and sem_timedwait() are checked in tst-cancel1[2345] tests.
+
+ mq_send(), mq_timedsend(), mq_receive() and mq_timedreceive() are checked
+ in tst-mqueue8{,x} tests.
+
+ aio_suspend() is tested in tst-cancel17.
+
+ clock_nanosleep() is tested in tst-cancel18.
+*/
+
+/* Pipe descriptors. */
+static int fds[2];
+
+/* Temporary file descriptor, to be closed after each round. */
+static int tempfd = -1;
+static int tempfd2 = -1;
+/* Name of temporary file to be removed after each round. */
+static char *tempfname;
+/* Temporary message queue. */
+static int tempmsg = -1;
+
+/* Often used barrier for two threads. */
+static pthread_barrier_t b2;
+
+
+#ifndef IPC_ADDVAL
+# define IPC_ADDVAL 0
+#endif
+
+#define WRITE_BUFFER_SIZE 4096
+
+/* Cleanup handling test. */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+
+static void *
+tf_read (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[100];
+ s = read (fd, buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_readv (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[100];
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ s = readv (fd, iov, 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_write (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[1];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[WRITE_BUFFER_SIZE];
+ memset (buf, '\0', sizeof (buf));
+ s = write (fd, buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_writev (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[1];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ ssize_t s;
+ pthread_cleanup_push (cl, NULL);
+
+ char buf[WRITE_BUFFER_SIZE];
+ memset (buf, '\0', sizeof (buf));
+ struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+ s = writev (fd, iov, 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+ exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ sleep (arg == NULL ? 1000000 : 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ usleep (arg == NULL ? (useconds_t) ULONG_MAX : 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: usleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fd, &rfs);
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = select (fd + 1, &rfs, NULL, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ fd_set rfs;
+ FD_ZERO (&rfs);
+ FD_SET (fd, &rfs);
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = pselect (fd + 1, &rfs, NULL, NULL, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = poll (rfs, 1, -1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_ppoll (void *arg)
+{
+ int fd;
+ int r;
+
+ if (arg == NULL)
+ fd = fds[0];
+ else
+ {
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = fd = mkstemp (fname);
+ if (fd == -1)
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ unlink (fname);
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = ppoll (rfs, 1, NULL, NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: ppoll returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = wait (NULL);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+ s = waitpid (-1, NULL, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Make the program disappear after a while. */
+ if (arg == NULL)
+ sleep (10);
+ exit (0);
+ }
+
+ int r;
+ if (arg != NULL)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int s;
+ pthread_cleanup_push (cl, NULL);
+
+#ifndef WEXITED
+# define WEXITED 0
+#endif
+ siginfo_t si;
+ s = waitid (P_PID, pid, &si, WEXITED);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+ strerror (errno));
+
+ exit (1);
+}
+
+
+static void *
+tf_sigpause (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Just for fun block the cancellation signal. We need to use
+ __xpg_sigpause since otherwise we will get the BSD version. */
+ //__xpg_sigpause (SIGCANCEL);
+
+ __sigpause (SIGCANCEL, 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigpause returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigsuspend (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Just for fun block all signals. */
+ sigset_t mask;
+ sigfillset (&mask);
+ sigsuspend (&mask);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigsuspend returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigwait (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int sig;
+ pthread_cleanup_push (cl, NULL);
+
+ /* Wait for SIGUSR1. */
+ sigwait (&mask, &sig);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigwait returned with signal %d\n", __FUNCTION__, sig);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigwaitinfo (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ siginfo_t info;
+ pthread_cleanup_push (cl, NULL);
+
+ /* Wait for SIGUSR1. */
+ sigwaitinfo (&mask, &info);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigwaitinfo returned with signal %d\n", __FUNCTION__,
+ info.si_signo);
+
+ exit (1);
+}
+
+
+static void *
+tf_sigtimedwait (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ /* Block SIGUSR1. */
+ sigset_t mask;
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+ {
+ printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ /* Wait for SIGUSR1. */
+ siginfo_t info;
+ struct timespec ts = { .tv_sec = 60, .tv_nsec = 0 };
+ pthread_cleanup_push (cl, NULL);
+
+ sigtimedwait (&mask, &info, &ts);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sigtimedwait returned with signal %d\n", __FUNCTION__,
+ info.si_signo);
+
+ exit (1);
+}
+
+
+static void *
+tf_pause (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ pause ();
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pause returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_accept (void *arg)
+{
+ struct sockaddr_un sun;
+ /* To test a non-blocking accept call we make the call file by using
+ a datagrame socket. */
+ int pf = arg == NULL ? SOCK_STREAM : SOCK_DGRAM;
+
+ tempfd = socket (AF_UNIX, pf, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-1-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ unlink (sun.sun_path);
+
+ listen (tempfd, 5);
+
+ socklen_t len = sizeof (sun);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ accept (tempfd, (struct sockaddr *) &sun, &len);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: accept returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_send (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+ {
+ printf ("%s: connect failed\n", __FUNCTION__);
+ exit(1);
+ }
+
+ unlink (sun.sun_path);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Very large block, so that the send call blocks. */
+ char mem[700000];
+
+ send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: send returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recv (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-3-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+ {
+ printf ("%s: connect failed\n", __FUNCTION__);
+ exit(1);
+ }
+
+ unlink (sun.sun_path);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+
+ recv (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recv returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recvfrom (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-4-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+ socklen_t len = sizeof (sun);
+
+ recvfrom (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0,
+ (struct sockaddr *) &sun, &len);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recvfrom returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_recvmsg (void *arg)
+{
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-5-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[70];
+ struct iovec iov[1];
+ iov[0].iov_base = mem;
+ iov[0].iov_len = arg == NULL ? sizeof (mem) : 0;
+
+ struct msghdr m;
+ m.msg_name = &sun;
+ m.msg_namelen = sizeof (sun);
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ m.msg_control = NULL;
+ m.msg_controllen = 0;
+
+ recvmsg (tempfd2, &m, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: recvmsg returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_open (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which open()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ open ("Makefile", O_RDONLY);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: open returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_close (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which close()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ char fname[] = "/tmp/tst-cancel-fd-XXXXXX";
+ tempfd = mkstemp (fname);
+ if (tempfd == -1)
+ {
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ exit (1);
+ }
+ unlink (fname);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ close (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: close returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_pread (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pread()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pread (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pread returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_pwrite (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pwrite()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = mkstemp (fname);
+ if (tempfd == -1)
+ {
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ exit (1);
+ }
+ unlink (fname);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pwrite (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pwrite returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_fsync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which fsync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ fsync (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: fsync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_fdatasync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which fdatasync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ fdatasync (tempfd);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: fdatasync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_msync (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which msync()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+ void *p = mmap (NULL, 10, PROT_READ, MAP_SHARED, tempfd, 0);
+ if (p == MAP_FAILED)
+ {
+ printf ("%s: mmap failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ msync (p, 10, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msync returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sendto (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendto()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-6-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[1];
+
+ sendto (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0,
+ (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path) + strlen (sun.sun_path) + 1);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sendto returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_sendmsg (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendmsg()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-7-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[1];
+ struct iovec iov[1];
+ iov[0].iov_base = mem;
+ iov[0].iov_len = 1;
+
+ struct msghdr m;
+ m.msg_name = &sun;
+ m.msg_namelen = (offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1);
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ m.msg_control = NULL;
+ m.msg_controllen = 0;
+
+ sendmsg (tempfd2, &m, 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: sendmsg returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_creat (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which sendmsg()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ creat ("tmp/tst-cancel-4-should-not-exist", 0666);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: creat returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_connect (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which connect()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ struct sockaddr_un sun;
+
+ tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd == -1)
+ {
+ printf ("%s: first socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int tries = 0;
+ do
+ {
+ if (++tries > 10)
+ {
+ printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+ }
+
+ strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+ if (mktemp (sun.sun_path) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
+ sun.sun_family = AF_UNIX;
+ }
+ while (bind (tempfd, (struct sockaddr *) &sun,
+ offsetof (struct sockaddr_un, sun_path)
+ + strlen (sun.sun_path) + 1) != 0);
+ tempfname = strdup (sun.sun_path);
+
+ listen (tempfd, 5);
+
+ tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+ if (tempfd2 == -1)
+ {
+ printf ("%s: second socket call failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun));
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: connect returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_tcdrain (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which tcdrain()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ /* Regardless of stderr being a terminal, the tcdrain call should be
+ canceled. */
+ tcdrain (STDERR_FILENO);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: tcdrain returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+
+static void *
+tf_msgrcv (void *arg)
+{
+ tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+ if (tempmsg == -1)
+ {
+ printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ if (arg != NULL)
+ {
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ ssize_t s;
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct
+ {
+ long int type;
+ char mem[10];
+ } m;
+ int randnr;
+ /* We need a positive random number. */
+ do
+ randnr = random () % 64000;
+ while (randnr <= 0);
+ do
+ {
+ errno = 0;
+ s = msgrcv (tempmsg, (struct msgbuf *) &m, 10, randnr, 0);
+ }
+ while (errno == EIDRM || errno == EINTR);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msgrcv returned %zd with errno = %m\n", __FUNCTION__, s);
+
+ msgctl (tempmsg, IPC_RMID, NULL);
+
+ exit (1);
+}
+
+
+static void *
+tf_msgsnd (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which msgsnd()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+ if (tempmsg == -1)
+ {
+ printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ struct
+ {
+ long int type;
+ char mem[1];
+ } m;
+ /* We need a positive random number. */
+ do
+ m.type = random () % 64000;
+ while (m.type <= 0);
+ msgsnd (tempmsg, (struct msgbuf *) &m, sizeof (m.mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: msgsnd returned\n", __FUNCTION__);
+
+ msgctl (tempmsg, IPC_RMID, NULL);
+
+ exit (1);
+}
+
+
+static struct
+{
+ const char *name;
+ void *(*tf) (void *);
+ int nb;
+ int only_early;
+} tests[] =
+{
+#define ADD_TEST(name, nbar, early) { #name, tf_##name, nbar, early }
+ ADD_TEST (read, 2, 0),
+ ADD_TEST (readv, 2, 0),
+ ADD_TEST (select, 2, 0),
+ ADD_TEST (pselect, 2, 0),
+ ADD_TEST (poll, 2, 0),
+ ADD_TEST (ppoll, 2, 0),
+ ADD_TEST (write, 2, 0),
+ ADD_TEST (writev, 2, 0),
+ ADD_TEST (sleep, 2, 0),
+ ADD_TEST (usleep, 2, 0),
+ ADD_TEST (nanosleep, 2, 0),
+ ADD_TEST (wait, 2, 0),
+ ADD_TEST (waitid, 2, 0),
+ ADD_TEST (waitpid, 2, 0),
+ ADD_TEST (sigpause, 2, 0),
+ ADD_TEST (sigsuspend, 2, 0),
+ ADD_TEST (sigwait, 2, 0),
+ ADD_TEST (sigwaitinfo, 2, 0),
+ ADD_TEST (sigtimedwait, 2, 0),
+ ADD_TEST (pause, 2, 0),
+ ADD_TEST (accept, 2, 0),
+ ADD_TEST (send, 2, 0),
+ ADD_TEST (recv, 2, 0),
+ ADD_TEST (recvfrom, 2, 0),
+ ADD_TEST (recvmsg, 2, 0),
+ ADD_TEST (open, 2, 1),
+ ADD_TEST (close, 2, 1),
+ ADD_TEST (pread, 2, 1),
+ ADD_TEST (pwrite, 2, 1),
+ ADD_TEST (fsync, 2, 1),
+ ADD_TEST (fdatasync, 2, 1),
+ ADD_TEST (msync, 2, 1),
+ ADD_TEST (sendto, 2, 1),
+ ADD_TEST (sendmsg, 2, 1),
+ ADD_TEST (creat, 2, 1),
+ ADD_TEST (connect, 2, 1),
+ ADD_TEST (tcdrain, 2, 1),
+ ADD_TEST (msgrcv, 2, 0),
+ ADD_TEST (msgsnd, 2, 1),
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+ int val;
+ socklen_t len;
+
+ if (socketpair (AF_UNIX, SOCK_STREAM, PF_UNIX, fds) != 0)
+ {
+ perror ("socketpair");
+ exit (1);
+ }
+
+ val = 1;
+ len = sizeof(val);
+ setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+ if (getsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, &len) < 0)
+ {
+ perror ("getsockopt");
+ exit (1);
+ }
+ if (val >= WRITE_BUFFER_SIZE)
+ {
+ puts ("minimum write buffer size too large");
+ exit (1);
+ }
+ setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+
+ int result = 0;
+ size_t cnt;
+ for (cnt = 0; cnt < ntest_tf; ++cnt)
+ {
+ if (tests[cnt].only_early)
+ continue;
+
+ if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ /* Reset the counter for the cleanup handler. */
+ cl_called = 0;
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+ {
+ printf ("create for '%s' test failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ while (nanosleep (&ts, &ts) != 0)
+ continue;
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("cancel for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("join for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ printf ("thread for '%s' not canceled\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_barrier_destroy (&b2) != 0)
+ {
+ puts ("barrier_destroy failed");
+ result = 1;
+ continue;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once for '%s'\n",
+ tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
+
+ if (tempfd != -1)
+ {
+ close (tempfd);
+ tempfd = -1;
+ }
+ if (tempfd2 != -1)
+ {
+ close (tempfd2);
+ tempfd2 = -1;
+ }
+ if (tempfname != NULL)
+ {
+ unlink (tempfname);
+ free (tempfname);
+ tempfname = NULL;
+ }
+ if (tempmsg != -1)
+ {
+ msgctl (tempmsg, IPC_RMID, NULL);
+ tempmsg = -1;
+ }
+ }
+
+ for (cnt = 0; cnt < ntest_tf; ++cnt)
+ {
+ if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ /* Reset the counter for the cleanup handler. */
+ cl_called = 0;
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
+ {
+ printf ("create for '%s' test failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ printf ("cancel for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ result = 1;
+ continue;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("join for '%s' failed\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ printf ("thread for '%s' not canceled\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ if (pthread_barrier_destroy (&b2) != 0)
+ {
+ puts ("barrier_destroy failed");
+ result = 1;
+ continue;
+ }
+
+ if (cl_called == 0)
+ {
+ printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+ result = 1;
+ continue;
+ }
+ if (cl_called > 1)
+ {
+ printf ("cleanup handler called more than once for '%s'\n",
+ tests[cnt].name);
+ result = 1;
+ continue;
+ }
+
+ printf ("early cancel test of '%s' successful\n", tests[cnt].name);
+
+ if (tempfd != -1)
+ {
+ close (tempfd);
+ tempfd = -1;
+ }
+ if (tempfd2 != -1)
+ {
+ close (tempfd2);
+ tempfd2 = -1;
+ }
+ if (tempfname != NULL)
+ {
+ unlink (tempfname);
+ free (tempfname);
+ tempfname = NULL;
+ }
+ if (tempmsg != -1)
+ {
+ msgctl (tempmsg, IPC_RMID, NULL);
+ tempmsg = -1;
+ }
+ }
+
+ return result;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel5.c b/test/nptl/tst-cancel5.c
new file mode 100644
index 000000000..1c879eba8
--- /dev/null
+++ b/test/nptl/tst-cancel5.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/test/nptl/tst-cancelx10.c b/test/nptl/tst-cancelx10.c
new file mode 100644
index 000000000..e5bbb34e6
--- /dev/null
+++ b/test/nptl/tst-cancelx10.c
@@ -0,0 +1 @@
+#include "tst-cancel10.c"
diff --git a/test/nptl/tst-cancelx11.c b/test/nptl/tst-cancelx11.c
new file mode 100644
index 000000000..ffcc2eefc
--- /dev/null
+++ b/test/nptl/tst-cancelx11.c
@@ -0,0 +1 @@
+#include "tst-cancel11.c"
diff --git a/test/nptl/tst-cancelx12.c b/test/nptl/tst-cancelx12.c
new file mode 100644
index 000000000..f90ae61ba
--- /dev/null
+++ b/test/nptl/tst-cancelx12.c
@@ -0,0 +1 @@
+#include "tst-cancel12.c"
diff --git a/test/nptl/tst-cancelx13.c b/test/nptl/tst-cancelx13.c
new file mode 100644
index 000000000..37c4c39c3
--- /dev/null
+++ b/test/nptl/tst-cancelx13.c
@@ -0,0 +1 @@
+#include "tst-cancel13.c"
diff --git a/test/nptl/tst-cancelx14.c b/test/nptl/tst-cancelx14.c
new file mode 100644
index 000000000..ba4e77584
--- /dev/null
+++ b/test/nptl/tst-cancelx14.c
@@ -0,0 +1 @@
+#include "tst-cancel14.c"
diff --git a/test/nptl/tst-cancelx15.c b/test/nptl/tst-cancelx15.c
new file mode 100644
index 000000000..005c1f6e3
--- /dev/null
+++ b/test/nptl/tst-cancelx15.c
@@ -0,0 +1 @@
+#include "tst-cancel15.c"
diff --git a/test/nptl/tst-cancelx16.c b/test/nptl/tst-cancelx16.c
new file mode 100644
index 000000000..99af3b197
--- /dev/null
+++ b/test/nptl/tst-cancelx16.c
@@ -0,0 +1 @@
+#include "tst-cancel16.c"
diff --git a/test/nptl/tst-cancelx18.c b/test/nptl/tst-cancelx18.c
new file mode 100644
index 000000000..56da18f38
--- /dev/null
+++ b/test/nptl/tst-cancelx18.c
@@ -0,0 +1 @@
+#include "tst-cancel18.c"
diff --git a/test/nptl/tst-cancelx2.c b/test/nptl/tst-cancelx2.c
new file mode 100644
index 000000000..95dc8a857
--- /dev/null
+++ b/test/nptl/tst-cancelx2.c
@@ -0,0 +1 @@
+#include "tst-cancel2.c"
diff --git a/test/nptl/tst-cancelx20.c b/test/nptl/tst-cancelx20.c
new file mode 100644
index 000000000..6bd86376c
--- /dev/null
+++ b/test/nptl/tst-cancelx20.c
@@ -0,0 +1 @@
+#include "tst-cancel20.c"
diff --git a/test/nptl/tst-cancelx21.c b/test/nptl/tst-cancelx21.c
new file mode 100644
index 000000000..2a01061ea
--- /dev/null
+++ b/test/nptl/tst-cancelx21.c
@@ -0,0 +1 @@
+#include "tst-cancel21.c"
diff --git a/test/nptl/tst-cancelx3.c b/test/nptl/tst-cancelx3.c
new file mode 100644
index 000000000..3937f10b9
--- /dev/null
+++ b/test/nptl/tst-cancelx3.c
@@ -0,0 +1 @@
+#include "tst-cancel3.c"
diff --git a/test/nptl/tst-cancelx4.c b/test/nptl/tst-cancelx4.c
new file mode 100644
index 000000000..1c879eba8
--- /dev/null
+++ b/test/nptl/tst-cancelx4.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/test/nptl/tst-cancelx6.c b/test/nptl/tst-cancelx6.c
new file mode 100644
index 000000000..6926e21c2
--- /dev/null
+++ b/test/nptl/tst-cancelx6.c
@@ -0,0 +1 @@
+#include "tst-cancel6.c"
diff --git a/test/nptl/tst-cancelx7.c b/test/nptl/tst-cancelx7.c
new file mode 100644
index 000000000..4df1a5881
--- /dev/null
+++ b/test/nptl/tst-cancelx7.c
@@ -0,0 +1 @@
+#include "tst-cancel7.c"
diff --git a/test/nptl/tst-cancelx8.c b/test/nptl/tst-cancelx8.c
new file mode 100644
index 000000000..0555c7ceb
--- /dev/null
+++ b/test/nptl/tst-cancelx8.c
@@ -0,0 +1 @@
+#include "tst-cancel8.c"
diff --git a/test/nptl/tst-cancelx9.c b/test/nptl/tst-cancelx9.c
new file mode 100644
index 000000000..9d84663d7
--- /dev/null
+++ b/test/nptl/tst-cancelx9.c
@@ -0,0 +1 @@
+#include "tst-cancel9.c"
diff --git a/test/nptl/tst-cleanupx0.c b/test/nptl/tst-cleanupx0.c
new file mode 100644
index 000000000..0012ab1b2
--- /dev/null
+++ b/test/nptl/tst-cleanupx0.c
@@ -0,0 +1 @@
+#include "tst-cleanup0.c"
diff --git a/test/nptl/tst-cleanupx1.c b/test/nptl/tst-cleanupx1.c
new file mode 100644
index 000000000..21e9e58bd
--- /dev/null
+++ b/test/nptl/tst-cleanupx1.c
@@ -0,0 +1 @@
+#include "tst-cleanup1.c"
diff --git a/test/nptl/tst-cleanupx2.c b/test/nptl/tst-cleanupx2.c
new file mode 100644
index 000000000..8b9e35093
--- /dev/null
+++ b/test/nptl/tst-cleanupx2.c
@@ -0,0 +1 @@
+#include "tst-cleanup2.c"
diff --git a/test/nptl/tst-cleanupx3.c b/test/nptl/tst-cleanupx3.c
new file mode 100644
index 000000000..90baf904f
--- /dev/null
+++ b/test/nptl/tst-cleanupx3.c
@@ -0,0 +1 @@
+#include "tst-cleanup3.c"
diff --git a/test/nptl/tst-cleanupx4.c b/test/nptl/tst-cleanupx4.c
new file mode 100644
index 000000000..8dea954b5
--- /dev/null
+++ b/test/nptl/tst-cleanupx4.c
@@ -0,0 +1 @@
+#include "tst-cleanup4.c"
diff --git a/test/nptl/tst-cond22.c b/test/nptl/tst-cond22.c
new file mode 100644
index 000000000..bd978e50c
--- /dev/null
+++ b/test/nptl/tst-cond22.c
@@ -0,0 +1,160 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_barrier_t b;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *arg)
+{
+ pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ printf ("%s: mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __func__);
+ exit (1);
+ }
+ pthread_cleanup_push (cl, NULL);
+ /* We have to loop here because the cancellation might come after
+ the cond_wait call left the cancelable area and is then waiting
+ on the mutex. In this case the beginning of the second cond_wait
+ call will cause the cancellation to happen. */
+ do
+ if (pthread_cond_wait (&c, &m) != 0)
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+ while (arg == NULL);
+ pthread_cleanup_pop (0);
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int status = 0;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ return 1;
+ }
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ return 1;
+ }
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+ if (pthread_cond_signal (&c) != 0)
+ {
+ puts ("1st cond_signal failed");
+ return 1;
+ }
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("1st mutex_unlock failed");
+ return 1;
+ }
+ void *res;
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("1st join failed");
+ return 1;
+ }
+ if (res != PTHREAD_CANCELED)
+ {
+ puts ("first thread not canceled");
+ status = 1;
+ }
+
+ printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+ c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+ c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+ c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+ if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
+ {
+ puts ("2nd create failed");
+ return 1;
+ }
+ e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("2nd barrier_wait failed");
+ return 1;
+ }
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+ if (pthread_cond_signal (&c) != 0)
+ {
+ puts ("2nd cond_signal failed");
+ return 1;
+ }
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("2nd mutex_unlock failed");
+ return 1;
+ }
+ if (pthread_join (th, &res) != 0)
+ {
+ puts ("2nd join failed");
+ return 1;
+ }
+ if (res != NULL)
+ {
+ puts ("2nd thread canceled");
+ status = 1;
+ }
+
+ printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+ c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+ c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+ c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond23.c b/test/nptl/tst-cond23.c
new file mode 100644
index 000000000..254d821cc
--- /dev/null
+++ b/test/nptl/tst-cond23.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2008.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+check (pthread_condattr_t *condattr, int pshared, clockid_t cl)
+{
+ clockid_t cl2;
+ if (pthread_condattr_getclock (condattr, &cl2) != 0)
+ {
+ puts ("condattr_getclock failed");
+ return 1;
+ }
+ if (cl != cl2)
+ {
+ printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+ (int) cl2, (int) cl);
+ return 1;
+ }
+
+ int p;
+ if (pthread_condattr_getpshared (condattr, &p) != 0)
+ {
+ puts ("condattr_getpshared failed");
+ return 1;
+ }
+ else if (p != pshared)
+ {
+ printf ("condattr_getpshared returned wrong value: %d, expected %d\n",
+ p, pshared);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+run_test (clockid_t cl)
+{
+ pthread_condattr_t condattr;
+
+ printf ("clock = %d\n", (int) cl);
+
+ if (pthread_condattr_init (&condattr) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("1st condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("1st condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("2nd condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+ {
+ puts ("2nd condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("3rd condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+ return 1;
+
+ if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("3rd condattr_setpshared failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+ return 1;
+
+ if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+ {
+ puts ("4th condattr_setclock failed");
+ return 1;
+ }
+
+ if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+ return 1;
+
+ if (pthread_condattr_destroy (&condattr) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+ puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+ return 0;
+
+#else
+
+ int res = run_test (CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+# if _POSIX_MONOTONIC_CLOCK == 0
+ int e = sysconf (_SC_MONOTONIC_CLOCK);
+ if (e < 0)
+ puts ("CLOCK_MONOTONIC not supported");
+ else if (e == 0)
+ {
+ puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+ res = 1;
+ }
+ else
+# endif
+ res |= run_test (CLOCK_MONOTONIC);
+# else
+ puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+ return res;
+#endif
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-dlsym1.c b/test/nptl/tst-dlsym1.c
new file mode 100644
index 000000000..3744570c7
--- /dev/null
+++ b/test/nptl/tst-dlsym1.c
@@ -0,0 +1,66 @@
+/* Test case by Hui Huang <hui.huang@sun.com>. */
+#include <dlfcn.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static void *
+start_routine (void *args)
+{
+ int i;
+ void **addrs = (void **) args;
+ for (i = 0; i < 10000; ++i)
+ addrs[i % 1024] = dlsym (NULL, "does_not_exist");
+
+ return addrs;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t tid1, tid2, tid3;
+
+ void *addrs1[1024];
+ void *addrs2[1024];
+ void *addrs3[1024];
+
+ if (pthread_create (&tid1, NULL, start_routine, addrs1) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+ if (pthread_create (&tid2, NULL, start_routine, addrs2) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+ if (pthread_create (&tid3, NULL, start_routine, addrs3) != 0)
+ {
+ puts ("3rd create failed");
+ exit (1);
+ }
+
+ if (pthread_join (tid1, NULL) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+ if (pthread_join (tid2, NULL) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+ if (pthread_join (tid3, NULL) != 0)
+ {
+ puts ("2rd join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-fini1.c b/test/nptl/tst-fini1.c
new file mode 100644
index 000000000..bec4be1d3
--- /dev/null
+++ b/test/nptl/tst-fini1.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <unistd.h>
+
+extern void m (void);
+
+int
+main (void)
+{
+ alarm (5);
+
+ m ();
+
+ /* The destructor is supposed to run now. Make sure that if it is
+ not we will notice it by using 42 as the exit code. In case the
+ destructor is run it will terminate with status zero. */
+ return 42;
+}
diff --git a/test/nptl/tst-fini1mod.c b/test/nptl/tst-fini1mod.c
new file mode 100644
index 000000000..492d9ffb8
--- /dev/null
+++ b/test/nptl/tst-fini1mod.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ int fds[2];
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ char buf[10];
+ read (fds[0], buf, sizeof (buf));
+
+ puts ("read returned");
+ exit (1);
+}
+
+static pthread_t th;
+
+static void
+__attribute ((destructor))
+dest (void)
+{
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ _exit (1);
+ }
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ _exit (1);
+ }
+ /* Exit successfully. */
+ _exit (0);
+}
+
+void
+m (void)
+{
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ _exit (1);
+ }
+}
diff --git a/test/nptl/tst-getpid1.c b/test/nptl/tst-getpid1.c
new file mode 100644
index 000000000..4d25b0de7
--- /dev/null
+++ b/test/nptl/tst-getpid1.c
@@ -0,0 +1,122 @@
+#include <sched.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <bits/stackinfo.h>
+
+#ifndef TEST_CLONE_FLAGS
+#define TEST_CLONE_FLAGS 0
+#endif
+
+static int sig;
+
+static int
+f (void *a)
+{
+ puts ("in f");
+ union sigval sival;
+ sival.sival_int = getpid ();
+ printf ("pid = %d\n", sival.sival_int);
+ if (sigqueue (getppid (), sig, sival) != 0)
+ return 1;
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ int mypid = getpid ();
+
+ sig = SIGRTMIN;
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, sig);
+ if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ printf ("sigprocmask failed: %m\n");
+ return 1;
+ }
+
+#ifdef __ia64__
+ extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+ size_t __child_stack_size, int __flags,
+ void *__arg, ...);
+ char st[256 * 1024] __attribute__ ((aligned));
+ pid_t p = __clone2 (f, st, sizeof (st), TEST_CLONE_FLAGS, 0);
+#else
+ char st[128 * 1024] __attribute__ ((aligned));
+# if _STACK_GROWS_DOWN
+ pid_t p = clone (f, st + sizeof (st), TEST_CLONE_FLAGS, 0);
+# elif _STACK_GROWS_UP
+ pid_t p = clone (f, st, TEST_CLONE_FLAGS, 0);
+# else
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+# endif
+#endif
+ if (p == -1)
+ {
+ printf("clone failed: %m\n");
+ return 1;
+ }
+ printf ("new thread: %d\n", (int) p);
+
+ siginfo_t si;
+ do
+ if (sigwaitinfo (&ss, &si) < 0)
+ {
+ printf("sigwaitinfo failed: %m\n");
+ kill (p, SIGKILL);
+ return 1;
+ }
+ while (si.si_signo != sig || si.si_code != SI_QUEUE);
+
+ int e;
+ if (waitpid (p, &e, __WCLONE) != p)
+ {
+ puts ("waitpid failed");
+ kill (p, SIGKILL);
+ return 1;
+ }
+ if (!WIFEXITED (e))
+ {
+ if (WIFSIGNALED (e))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (e) != 0)
+ {
+ printf ("exit code %d\n", WEXITSTATUS (e));
+ return 1;
+ }
+
+ if (si.si_int != (int) p)
+ {
+ printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
+ kill (p, SIGKILL);
+ return 1;
+ }
+
+ if (si.si_pid != p)
+ {
+ printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
+ kill (p, SIGKILL);
+ return 1;
+ }
+
+ if (getpid () != mypid)
+ {
+ puts ("my PID changed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-getpid2.c b/test/nptl/tst-getpid2.c
new file mode 100644
index 000000000..fc98cb60d
--- /dev/null
+++ b/test/nptl/tst-getpid2.c
@@ -0,0 +1,2 @@
+#define TEST_CLONE_FLAGS CLONE_VM
+#include "tst-getpid1.c"
diff --git a/test/nptl/tst-getpid3.c b/test/nptl/tst-getpid3.c
new file mode 100644
index 000000000..f1e77f6b1
--- /dev/null
+++ b/test/nptl/tst-getpid3.c
@@ -0,0 +1,114 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t pid;
+
+static void *
+pid_thread (void *arg)
+{
+ if (pid != getpid ())
+ {
+ printf ("pid wrong in thread: should be %d, is %d\n",
+ (int) pid, (int) getpid ());
+ return (void *) 1L;
+ }
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ pid = getpid ();
+
+ pthread_t thr;
+ int ret = pthread_create (&thr, NULL, pid_thread, NULL);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+
+ void *thr_ret;
+ ret = pthread_join (thr, &thr_ret);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+ else if (thr_ret)
+ {
+ printf ("thread getpid failed\n");
+ return 1;
+ }
+
+ pid_t child = fork ();
+ if (child == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+ else if (child == 0)
+ {
+ if (pid == getpid ())
+ {
+ puts ("pid did not change after fork");
+ exit (1);
+ }
+
+ pid = getpid ();
+ ret = pthread_create (&thr, NULL, pid_thread, NULL);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+
+ ret = pthread_join (thr, &thr_ret);
+ if (ret)
+ {
+ printf ("pthread_create failed: %d\n", ret);
+ return 1;
+ }
+ else if (thr_ret)
+ {
+ printf ("thread getpid failed\n");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+ {
+ puts ("waitpid failed");
+ kill (child, SIGKILL);
+ return 1;
+ }
+
+ if (!WIFEXITED (status))
+ {
+ if (WIFSIGNALED (status))
+ printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
+ else
+ puts ("did not terminate correctly");
+ return 1;
+ }
+ if (WEXITSTATUS (status) != 0)
+ {
+ printf ("exit code %d\n", WEXITSTATUS (status));
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-initializers1-c89.c b/test/nptl/tst-initializers1-c89.c
new file mode 100644
index 000000000..7c27c1d54
--- /dev/null
+++ b/test/nptl/tst-initializers1-c89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/test/nptl/tst-initializers1-c99.c b/test/nptl/tst-initializers1-c99.c
new file mode 100644
index 000000000..7c27c1d54
--- /dev/null
+++ b/test/nptl/tst-initializers1-c99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/test/nptl/tst-initializers1-gnu89.c b/test/nptl/tst-initializers1-gnu89.c
new file mode 100644
index 000000000..7c27c1d54
--- /dev/null
+++ b/test/nptl/tst-initializers1-gnu89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/test/nptl/tst-initializers1-gnu99.c b/test/nptl/tst-initializers1-gnu99.c
new file mode 100644
index 000000000..7c27c1d54
--- /dev/null
+++ b/test/nptl/tst-initializers1-gnu99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/test/nptl/tst-join6.c b/test/nptl/tst-join6.c
new file mode 100644
index 000000000..0c9e7c056
--- /dev/null
+++ b/test/nptl/tst-join6.c
@@ -0,0 +1,2 @@
+#define WAIT_IN_CHILD 1
+#include "tst-join5.c"
diff --git a/test/nptl/tst-oddstacklimit.c b/test/nptl/tst-oddstacklimit.c
new file mode 100644
index 000000000..9fbef1889
--- /dev/null
+++ b/test/nptl/tst-oddstacklimit.c
@@ -0,0 +1 @@
+#include "tst-basic1.c"
diff --git a/test/nptl/tst-oncex3.c b/test/nptl/tst-oncex3.c
new file mode 100644
index 000000000..08225b88d
--- /dev/null
+++ b/test/nptl/tst-oncex3.c
@@ -0,0 +1 @@
+#include "tst-once3.c"
diff --git a/test/nptl/tst-oncex4.c b/test/nptl/tst-oncex4.c
new file mode 100644
index 000000000..9b4d98f3f
--- /dev/null
+++ b/test/nptl/tst-oncex4.c
@@ -0,0 +1 @@
+#include "tst-once4.c"
diff --git a/test/nptl/tst-rwlock2a.c b/test/nptl/tst-rwlock2a.c
new file mode 100644
index 000000000..615de5c01
--- /dev/null
+++ b/test/nptl/tst-rwlock2a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
+#include "tst-rwlock2.c"
diff --git a/test/nptl/tst-sem10.c b/test/nptl/tst-sem10.c
new file mode 100644
index 000000000..9f6e870a8
--- /dev/null
+++ b/test/nptl/tst-sem10.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2007.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static int
+do_test (void)
+{
+ sem_t s;
+ if (sem_init (&s, 0, 0) == -1)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ struct timeval tv;
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ return 1;
+ }
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ /* Set ts to yesterday. */
+ ts.tv_sec -= 86400;
+
+ int type_before;
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_before) != 0)
+ {
+ puts ("first pthread_setcanceltype failed");
+ return 1;
+ }
+
+ errno = 0;
+ if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
+ {
+ puts ("sem_timedwait succeeded");
+ return 1;
+ }
+ if (errno != ETIMEDOUT)
+ {
+ printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
+ errno);
+ return 1;
+ }
+
+ int type_after;
+ if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_after) != 0)
+ {
+ puts ("second pthread_setcanceltype failed");
+ return 1;
+ }
+ if (type_after != PTHREAD_CANCEL_DEFERRED)
+ {
+ puts ("sem_timedwait changed cancellation type");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-sem11.c b/test/nptl/tst-sem11.c
new file mode 100644
index 000000000..6633ddd1f
--- /dev/null
+++ b/test/nptl/tst-sem11.c
@@ -0,0 +1,76 @@
+#include <semaphore.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <internaltypes.h>
+
+#ifndef SEM_WAIT
+# define SEM_WAIT(s) sem_wait (s)
+#endif
+
+static void *
+tf (void *arg)
+{
+#ifdef PREPARE
+ PREPARE
+#endif
+ SEM_WAIT (arg);
+ return NULL;
+}
+
+int
+main (void)
+{
+ int tries = 5;
+ pthread_t th;
+ sem_t s;
+ again:
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ return 1;
+ }
+
+ struct new_sem *is = (struct new_sem *) &s;
+
+ if (is->nwaiters != 0)
+ {
+ puts ("nwaiters not initialized");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, &s) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("pthread_cancel failed");
+ return 1;
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("pthread_join failed");
+ return 1;
+ }
+ if (r != PTHREAD_CANCELED && --tries > 0)
+ {
+ /* Maybe we get the scheduling right the next time. */
+ sem_destroy (&s);
+ goto again;
+ }
+
+ if (is->nwaiters != 0)
+ {
+ puts ("nwaiters not reset");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/nptl/tst-sem12.c b/test/nptl/tst-sem12.c
new file mode 100644
index 000000000..71d02b70e
--- /dev/null
+++ b/test/nptl/tst-sem12.c
@@ -0,0 +1,14 @@
+#include <time.h>
+#include <sys/time.h>
+
+
+#define PREPARE \
+ struct timespec ts; \
+ struct timeval tv; \
+ gettimeofday (&tv, NULL); \
+ TIMEVAL_TO_TIMESPEC (&tv, &ts); \
+ ts.tv_sec += 60;
+
+#define SEM_WAIT(s) sem_timedwait (s, &ts)
+
+#include "tst-sem11.c"
diff --git a/test/nptl/tst-signal7.c b/test/nptl/tst-signal7.c
new file mode 100644
index 000000000..82ef11c2d
--- /dev/null
+++ b/test/nptl/tst-signal7.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <pthreadP.h>
+#include <signal.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+ errno = 0;
+ if (sigaction (SIGCANCEL, NULL, NULL) == 0)
+ {
+ puts ("sigaction(SIGCANCEL) did not fail");
+ result = 1;
+ }
+ else if (errno != EINVAL)
+ {
+ puts ("sigaction(SIGCANCEL) did not set errno to EINVAL");
+ result = 1;
+ }
+
+ errno = 0;
+ if (sigaction (SIGSETXID, NULL, NULL) == 0)
+ {
+ puts ("sigaction(SIGSETXID) did not fail");
+ result = 1;
+ }
+ else if (errno != EINVAL)
+ {
+ puts ("sigaction(SIGSETXID) did not set errno to EINVAL");
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tsd6.c b/test/nptl/tst-tsd6.c
new file mode 100644
index 000000000..debb1dd36
--- /dev/null
+++ b/test/nptl/tst-tsd6.c
@@ -0,0 +1,89 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define NKEYS 100
+static pthread_key_t keys[NKEYS];
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ void *res = NULL;
+ for (int i = 0; i < NKEYS; ++i)
+ {
+ void *p = pthread_getspecific (keys[i]);
+ pthread_setspecific (keys[i], (void *) 7);
+ if (p != NULL)
+ res = p;
+ }
+ if (arg != NULL)
+ {
+ pthread_barrier_wait (arg);
+ pthread_barrier_wait (arg);
+ }
+ return res;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_barrier_init (&b, NULL, 2);
+
+ for (int i = 0; i < NKEYS; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ puts ("cannot create keys");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &b) != 0)
+ {
+ puts ("cannot create thread in parent");
+ return 1;
+ }
+
+ pthread_barrier_wait (&b);
+
+ pid_t pid = fork ();
+ if (pid == 0)
+ {
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("cannot create thread in child");
+ exit (1);
+ }
+
+ void *res;
+ pthread_join (th, &res);
+
+ exit (res != NULL);
+ }
+ else if (pid == -1)
+ {
+ puts ("cannot create child process");
+ return 1;
+ }
+
+ int s;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
+ {
+ puts ("failing to wait for child process");
+ return 1;
+ }
+
+ pthread_barrier_wait (&b);
+ pthread_join (th, NULL);
+
+ return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-typesizes.c b/test/nptl/tst-typesizes.c
new file mode 100644
index 000000000..545cee6bd
--- /dev/null
+++ b/test/nptl/tst-typesizes.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <pthreadP.h>
+#include <semaphore.h>
+
+static const struct
+{
+ const char *name;
+ size_t expected;
+ size_t is;
+} types[] =
+ {
+#define T(t, c) \
+ { #t, c, sizeof (t) }
+ T (pthread_attr_t, __SIZEOF_PTHREAD_ATTR_T),
+ T (pthread_mutex_t, __SIZEOF_PTHREAD_MUTEX_T),
+ T (pthread_mutexattr_t, __SIZEOF_PTHREAD_MUTEXATTR_T),
+ T (pthread_cond_t, __SIZEOF_PTHREAD_COND_T),
+ T (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T),
+ T (pthread_rwlock_t, __SIZEOF_PTHREAD_RWLOCK_T),
+ T (pthread_rwlockattr_t, __SIZEOF_PTHREAD_RWLOCKATTR_T),
+ T (pthread_barrier_t, __SIZEOF_PTHREAD_BARRIER_T),
+ T (pthread_barrierattr_t, __SIZEOF_PTHREAD_BARRIERATTR_T)
+ };
+
+static int
+do_test (void)
+{
+ int result = 0;
+
+#define TEST_TYPE(name) \
+ printf ("%s: ", #name); \
+ if (sizeof (name) != sizeof (((name *) 0)->__size)) \
+ { \
+ printf ("expected %zu, is %zu\n", \
+ sizeof (((name *) 0)->__size), sizeof (name)); \
+ result = 1; \
+ } \
+ else \
+ puts ("OK")
+
+ TEST_TYPE (pthread_mutex_t);
+ TEST_TYPE (pthread_cond_t);
+ TEST_TYPE (pthread_rwlock_t);
+
+#define TEST_TYPE2(name, internal) \
+ printf ("%s: ", #name); \
+ if (sizeof (((name *) 0)->__size) < sizeof (internal)) \
+ { \
+ printf ("expected %zu, is %zu\n", \
+ sizeof (((name *) 0)->__size), sizeof (internal)); \
+ result = 1; \
+ } \
+ else \
+ puts ("OK")
+
+ TEST_TYPE2 (pthread_attr_t, struct pthread_attr);
+ TEST_TYPE2 (pthread_mutexattr_t, struct pthread_mutexattr);
+ TEST_TYPE2 (pthread_condattr_t, struct pthread_condattr);
+ TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
+ TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
+ TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
+ TEST_TYPE2 (sem_t, struct new_sem);
+ TEST_TYPE2 (sem_t, struct old_sem);
+
+ for (size_t i = 0; i < sizeof (types) / sizeof (types[0]); ++i)
+ if (types[i].expected != types[i].is)
+ {
+ printf ("%s: expected %zu, is %zu\n",
+ types[i].name, types[i].expected, types[i].is);
+ result = 1;
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-unload.c b/test/nptl/tst-unload.c
new file mode 100644
index 000000000..5c552e22a
--- /dev/null
+++ b/test/nptl/tst-unload.c
@@ -0,0 +1,47 @@
+/* Tests for non-unloading of libpthread.
+ Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+ void *p = dlopen ("libpthread.so.0", RTLD_LAZY);
+
+ if (p == NULL)
+ {
+ puts ("failed to load libpthread.so.0");
+ return 1;
+ }
+
+ if (dlclose (p) != 0)
+ {
+ puts ("dlclose (libpthread.so.0) failed");
+ return 1;
+ }
+
+ puts ("seems to work");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-vfork1.c b/test/nptl/tst-vfork1.c
new file mode 100644
index 000000000..1f36f1ff2
--- /dev/null
+++ b/test/nptl/tst-vfork1.c
@@ -0,0 +1,150 @@
+/* Test for vfork functions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* This test relies on non-POSIX functionality since the child
+ processes call write and getpid. */
+static int
+do_test (void)
+{
+ int result = 0;
+ int fd[2];
+
+ if (pipe (fd) == -1)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ /* First vfork() without previous getpid(). */
+ pid_t p1;
+ if ((p1 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("1st vfork failed");
+ result = 1;
+ }
+
+ pid_t p2 = 0;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("1st read failed");
+ result = 1;
+ }
+ int r;
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+ {
+ puts ("1st waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 1st child failed");
+ result = 1;
+ }
+
+ /* Main process' ID. */
+ pid_t p0 = getpid ();
+
+ /* vfork() again, but after a getpid() in the main process. */
+ pid_t p3;
+ if ((p3 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("2nd vfork failed");
+ result = 1;
+ }
+
+ pid_t p4;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("2nd read failed");
+ result = 1;
+ }
+ if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+ {
+ puts ("2nd waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 2nd child failed");
+ result = 1;
+ }
+
+ /* And getpid in the main process again. */
+ pid_t p5 = getpid ();
+
+ /* Analysis of the results. */
+ if (p0 != p5)
+ {
+ printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+ result = 1;
+ }
+
+ if (p0 == p1)
+ {
+ printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+ result = 1;
+ }
+
+ if (p1 != p2)
+ {
+ printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+ result = 1;
+ }
+
+ if (p0 == p3)
+ {
+ printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+ result = 1;
+ }
+
+ if (p3 != p4)
+ {
+ printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+ result = 1;
+ }
+
+ close (fd[0]);
+ close (fd[1]);
+
+ if (result == 0)
+ puts ("All OK");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-vfork1x.c b/test/nptl/tst-vfork1x.c
new file mode 100644
index 000000000..1f36f1ff2
--- /dev/null
+++ b/test/nptl/tst-vfork1x.c
@@ -0,0 +1,150 @@
+/* Test for vfork functions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* This test relies on non-POSIX functionality since the child
+ processes call write and getpid. */
+static int
+do_test (void)
+{
+ int result = 0;
+ int fd[2];
+
+ if (pipe (fd) == -1)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ /* First vfork() without previous getpid(). */
+ pid_t p1;
+ if ((p1 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("1st vfork failed");
+ result = 1;
+ }
+
+ pid_t p2 = 0;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("1st read failed");
+ result = 1;
+ }
+ int r;
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+ {
+ puts ("1st waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 1st child failed");
+ result = 1;
+ }
+
+ /* Main process' ID. */
+ pid_t p0 = getpid ();
+
+ /* vfork() again, but after a getpid() in the main process. */
+ pid_t p3;
+ if ((p3 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("2nd vfork failed");
+ result = 1;
+ }
+
+ pid_t p4;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("2nd read failed");
+ result = 1;
+ }
+ if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+ {
+ puts ("2nd waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 2nd child failed");
+ result = 1;
+ }
+
+ /* And getpid in the main process again. */
+ pid_t p5 = getpid ();
+
+ /* Analysis of the results. */
+ if (p0 != p5)
+ {
+ printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+ result = 1;
+ }
+
+ if (p0 == p1)
+ {
+ printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+ result = 1;
+ }
+
+ if (p1 != p2)
+ {
+ printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+ result = 1;
+ }
+
+ if (p0 == p3)
+ {
+ printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+ result = 1;
+ }
+
+ if (p3 != p4)
+ {
+ printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+ result = 1;
+ }
+
+ close (fd[0]);
+ close (fd[1]);
+
+ if (result == 0)
+ puts ("All OK");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-vfork2.c b/test/nptl/tst-vfork2.c
new file mode 100644
index 000000000..1d096e14a
--- /dev/null
+++ b/test/nptl/tst-vfork2.c
@@ -0,0 +1,199 @@
+/* Test for vfork functions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int raise_fail;
+
+static void
+alrm (int sig)
+{
+ if (raise (SIGUSR1) < 0)
+ raise_fail = 1;
+}
+
+/* This test relies on non-POSIX functionality since the child
+ processes call write, nanosleep and getpid. */
+static int
+do_test (void)
+{
+ int result = 0;
+ int fd[2];
+
+ signal (SIGUSR1, SIG_IGN);
+
+ struct sigaction sa;
+ sa.sa_handler = alrm;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (SIGALRM, &sa, NULL) < 0)
+ {
+ puts ("couldn't set up SIGALRM handler");
+ return 1;
+ }
+
+ if (pipe (fd) == -1)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ struct itimerval it;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 200 * 1000;
+ it.it_interval = it.it_value;
+ if (setitimer (ITIMER_REAL, &it, NULL) < 0)
+ {
+ puts ("couldn't set up timer");
+ return 1;
+ }
+
+ /* First vfork() without previous getpid(). */
+ pid_t p1;
+ if ((p1 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+
+ struct timespec ts;
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("1st vfork failed");
+ result = 1;
+ }
+
+ memset (&it, 0, sizeof (it));
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ pid_t p2 = 0;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("1st read failed");
+ result = 1;
+ }
+ int r;
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+ {
+ puts ("1st waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 1st child failed");
+ result = 1;
+ }
+
+ /* Main process' ID. */
+ pid_t p0 = getpid ();
+
+ /* vfork() again, but after a getpid() in the main process. */
+ pid_t p3;
+ if ((p3 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("2nd vfork failed");
+ result = 1;
+ }
+
+ pid_t p4;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("2nd read failed");
+ result = 1;
+ }
+ if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+ {
+ puts ("2nd waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 2nd child failed");
+ result = 1;
+ }
+
+ /* And getpid in the main process again. */
+ pid_t p5 = getpid ();
+
+ /* Analysis of the results. */
+ if (p0 != p5)
+ {
+ printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+ result = 1;
+ }
+
+ if (p0 == p1)
+ {
+ printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+ result = 1;
+ }
+
+ if (p1 != p2)
+ {
+ printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+ result = 1;
+ }
+
+ if (p0 == p3)
+ {
+ printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+ result = 1;
+ }
+
+ if (p3 != p4)
+ {
+ printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+ result = 1;
+ }
+
+ close (fd[0]);
+ close (fd[1]);
+
+ if (raise_fail)
+ {
+ puts ("raise failed");
+ result = 1;
+ }
+
+ if (result == 0)
+ puts ("All OK");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-vfork2x.c b/test/nptl/tst-vfork2x.c
new file mode 100644
index 000000000..1d096e14a
--- /dev/null
+++ b/test/nptl/tst-vfork2x.c
@@ -0,0 +1,199 @@
+/* Test for vfork functions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+int raise_fail;
+
+static void
+alrm (int sig)
+{
+ if (raise (SIGUSR1) < 0)
+ raise_fail = 1;
+}
+
+/* This test relies on non-POSIX functionality since the child
+ processes call write, nanosleep and getpid. */
+static int
+do_test (void)
+{
+ int result = 0;
+ int fd[2];
+
+ signal (SIGUSR1, SIG_IGN);
+
+ struct sigaction sa;
+ sa.sa_handler = alrm;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (SIGALRM, &sa, NULL) < 0)
+ {
+ puts ("couldn't set up SIGALRM handler");
+ return 1;
+ }
+
+ if (pipe (fd) == -1)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ struct itimerval it;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 200 * 1000;
+ it.it_interval = it.it_value;
+ if (setitimer (ITIMER_REAL, &it, NULL) < 0)
+ {
+ puts ("couldn't set up timer");
+ return 1;
+ }
+
+ /* First vfork() without previous getpid(). */
+ pid_t p1;
+ if ((p1 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+
+ struct timespec ts;
+ ts.tv_sec = 1;
+ ts.tv_nsec = 0;
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("1st vfork failed");
+ result = 1;
+ }
+
+ memset (&it, 0, sizeof (it));
+ setitimer (ITIMER_REAL, &it, NULL);
+
+ pid_t p2 = 0;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("1st read failed");
+ result = 1;
+ }
+ int r;
+ if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+ {
+ puts ("1st waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 1st child failed");
+ result = 1;
+ }
+
+ /* Main process' ID. */
+ pid_t p0 = getpid ();
+
+ /* vfork() again, but after a getpid() in the main process. */
+ pid_t p3;
+ if ((p3 = vfork ()) == 0)
+ {
+ pid_t p = getpid ();
+ _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+ }
+ else if (p1 == -1)
+ {
+ puts ("2nd vfork failed");
+ result = 1;
+ }
+
+ pid_t p4;
+ if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+ {
+ puts ("2nd read failed");
+ result = 1;
+ }
+ if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+ {
+ puts ("2nd waitpid failed");
+ result = 1;
+ }
+ else if (r != 0)
+ {
+ puts ("write in 2nd child failed");
+ result = 1;
+ }
+
+ /* And getpid in the main process again. */
+ pid_t p5 = getpid ();
+
+ /* Analysis of the results. */
+ if (p0 != p5)
+ {
+ printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+ result = 1;
+ }
+
+ if (p0 == p1)
+ {
+ printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+ result = 1;
+ }
+
+ if (p1 != p2)
+ {
+ printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+ result = 1;
+ }
+
+ if (p0 == p3)
+ {
+ printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+ result = 1;
+ }
+
+ if (p3 != p4)
+ {
+ printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+ result = 1;
+ }
+
+ close (fd[0]);
+ close (fd[1]);
+
+ if (raise_fail)
+ {
+ puts ("raise failed");
+ result = 1;
+ }
+
+ if (result == 0)
+ puts ("All OK");
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"