summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/nptl/Makefile15
-rw-r--r--test/nptl/tst-cancel11.c123
-rw-r--r--test/nptl/tst-cancel2.c100
-rw-r--r--test/nptl/tst-cancel20.c264
-rw-r--r--test/nptl/tst-cancel21.c294
-rw-r--r--test/nptl/tst-cancel22.c121
-rw-r--r--test/nptl/tst-cancel3.c98
-rw-r--r--test/nptl/tst-cancel6.c79
-rw-r--r--test/nptl/tst-cancel9.c126
-rw-r--r--test/nptl/tst-cleanup4.c198
-rw-r--r--test/nptl/tst-join5.c143
-rw-r--r--test/nptl/tst-key3.c156
12 files changed, 1711 insertions, 6 deletions
diff --git a/test/nptl/Makefile b/test/nptl/Makefile
index b963b7ede..4691ab814 100644
--- a/test/nptl/Makefile
+++ b/test/nptl/Makefile
@@ -87,10 +87,13 @@ TARGETS = tst-align tst-align2 \
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
tst-basic1 tst-basic2 tst-basic3 \
tst-basic4 tst-basic5 tst-basic6 \
- tst-cancel1 tst-cancel8 tst-cancel10 tst-cancel12 \
- tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16 \
- tst-cancel19 \
- tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
+ tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel6 \
+ tst-cancel8 tst-cancel9 tst-cancel10 tst-cancel11 \
+ tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
+ tst-cancel16 tst-cancel19 tst-cancel20 tst-cancel21 \
+ tst-cancel22 \
+ tst-cleanup0 tst-cleanup1 tst-cleanup2 \
+ tst-cleanup3 tst-cleanup4 \
tst-clock1 tst-clock2 \
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 \
tst-cond7 tst-cond8 tst-cond9 tst-cond10 tst-cond11 \
@@ -103,8 +106,8 @@ TARGETS = tst-align tst-align2 \
tst-flock1 tst-flock2 \
tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
tst-initializers1 \
- tst-join1 tst-join2 tst-join3 \
- tst-key1 tst-key2 tst-key4 \
+ tst-join1 tst-join2 tst-join3 tst-join5 \
+ tst-key1 tst-key2 tst-key3 tst-key4 \
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 \
tst-mutex6 tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a \
diff --git a/test/nptl/tst-cancel11.c b/test/nptl/tst-cancel11.c
new file mode 100644
index 000000000..235aef5c4
--- /dev/null
+++ b/test/nptl/tst-cancel11.c
@@ -0,0 +1,123 @@
+/* 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 <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+static int fd[2];
+
+
+static void
+cleanup (void *arg)
+{
+ static int ncall;
+
+ if (++ncall != 1)
+ {
+ puts ("second call to cleanup");
+ exit (1);
+ }
+
+ printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should block and be cancelable. */
+ char buf[20];
+ read (fd[0], buf, sizeof (buf));
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("1st barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("1st cancel failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel2.c b/test/nptl/tst-cancel2.c
new file mode 100644
index 000000000..6d80f8ae5
--- /dev/null
+++ b/test/nptl/tst-cancel2.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002 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. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ /* The buffer size must be larger than the pipe size so that the
+ write blocks. */
+ char buf[100000];
+
+ if (write (fd[1], buf, sizeof (buf)) == sizeof (buf))
+ {
+ puts ("write succeeded");
+ return (void *) 1l;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the write in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel20.c b/test/nptl/tst-cancel20.c
new file mode 100644
index 000000000..d88cb9caf
--- /dev/null
+++ b/test/nptl/tst-cancel20.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+ cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 1L);
+
+ in_sh_body = 1;
+ if (read (fd[2], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+ pthread_cleanup_push (cl, (void *) 2L);
+ sh_body ();
+ in_sh_body = 0;
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 3L);
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child thread: barrier_wait failed");
+ exit (1);
+ }
+
+ if (read (fd[0], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ read (fd[0], &c, 1);
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cl, (void *) 4L);
+ tf_body ();
+ pthread_cleanup_pop (0);
+ return NULL;
+}
+
+
+static int
+do_one_test (void)
+{
+ in_sh_body = 0;
+ cleanups = 0;
+ if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent thread: barrier_wait failed");
+ return 1;
+ }
+
+ sleep (1);
+
+ r = pthread_kill (th, SIGHUP);
+ if (r)
+ {
+ errno = r;
+ printf ("pthread_kill failed %m\n");
+ return 1;
+ }
+
+ while (in_sh_body == 0)
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the read in the child to return. */
+ close (fd[0]);
+ close (fd[1]);
+ close (fd[2]);
+ close (fd[3]);
+
+ void *ret;
+ if (pthread_join (th, &ret) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (ret != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ return 1;
+ }
+
+ if (cleanups != 0x1234L)
+ {
+ printf ("called cleanups %lx\n", cleanups);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int
+do_test (void)
+{
+ stack_t ss;
+ ss.ss_sp = malloc (2 * SIGSTKSZ);
+ if (ss.ss_sp == NULL)
+ {
+ puts ("failed to allocate alternate stack");
+ return 1;
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = 2 * SIGSTKSZ;
+ if (sigaltstack (&ss, NULL) < 0)
+ {
+ printf ("sigaltstack failed %m\n");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = 0 test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel21.c b/test/nptl/tst-cancel21.c
new file mode 100644
index 000000000..cc00cc168
--- /dev/null
+++ b/test/nptl/tst-cancel21.c
@@ -0,0 +1,294 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+ cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 1L);
+
+ in_sh_body = 1;
+ if (read (fd[2], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+ pthread_cleanup_push (cl, (void *) 2L);
+ sh_body ();
+ in_sh_body = 0;
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+ char c;
+
+ pthread_cleanup_push (cl, (void *) 3L);
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child thread: barrier_wait failed");
+ exit (1);
+ }
+
+ if (read (fd[0], &c, 1) == 1)
+ {
+ puts ("read succeeded");
+ exit (1);
+ }
+
+ read (fd[0], &c, 1);
+
+ pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th = (pthread_t) arg;
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent thread: barrier_wait failed");
+ exit (1);
+ }
+
+ sleep (1);
+
+ r = pthread_kill (th, SIGHUP);
+ if (r)
+ {
+ errno = r;
+ printf ("pthread_kill failed %m\n");
+ exit (1);
+ }
+
+ while (in_sh_body == 0)
+ sleep (1);
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ /* This will cause the read in the initial thread to return. */
+ close (fd[0]);
+ close (fd[1]);
+ close (fd[2]);
+ close (fd[3]);
+
+ void *ret;
+ if (pthread_join (th, &ret) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (ret != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ exit (1);
+ }
+
+ if (cleanups != 0x1234L)
+ {
+ printf ("called cleanups %lx\n", cleanups);
+ exit (1);
+ }
+
+ if (pthread_barrier_destroy (&b))
+ {
+ puts ("barrier destroy failed");
+ exit (1);
+ }
+
+ exit (0);
+}
+
+
+static int
+do_one_test (void)
+{
+ in_sh_body = 0;
+
+ pid_t pid = fork ();
+
+ if (pid == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (pid)
+ {
+ int status;
+ if (waitpid (pid, &status, 0) < 0)
+ {
+ printf ("waitpid failed %m\n");
+ return 1;
+ }
+
+ return !WIFEXITED (status) || WEXITSTATUS (status);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ cleanups = 0;
+ if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, (void *) 4L);
+ tf_body ();
+ pthread_cleanup_pop (0);
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ stack_t ss;
+ ss.ss_sp = malloc (2 * SIGSTKSZ);
+ if (ss.ss_sp == NULL)
+ {
+ puts ("failed to allocate alternate stack");
+ return 1;
+ }
+ ss.ss_flags = 0;
+ ss.ss_size = 2 * SIGSTKSZ;
+ if (sigaltstack (&ss, NULL) < 0)
+ {
+ printf ("sigaltstack failed %m\n");
+ return 1;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = 0 test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_handler = sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO test");
+ if (do_one_test ())
+ return 1;
+
+ sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ if (sigaction (SIGHUP, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+ if (do_one_test ())
+ return 1;
+
+ return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel22.c b/test/nptl/tst-cancel22.c
new file mode 100644
index 000000000..33bfc64a3
--- /dev/null
+++ b/test/nptl/tst-cancel22.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <unistd.h>
+
+pthread_barrier_t b;
+int seen;
+
+static void *
+tf (void *arg)
+{
+ int old;
+ int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
+ if (r != 0)
+ {
+ puts ("setcancelstate failed");
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ for (int i = 0; i < 10; ++i)
+ {
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+ }
+
+ seen = 1;
+ pthread_setcancelstate (old, NULL);
+
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+ TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+ 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 ("thread creation failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+ if (status != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ return 1;
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ puts ("barrier_destroy failed");
+ return 1;
+ }
+
+ if (seen != 1)
+ {
+ puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel3.c b/test/nptl/tst-cancel3.c
new file mode 100644
index 000000000..86c482bcc
--- /dev/null
+++ b/test/nptl/tst-cancel3.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2002 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. */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+
+ if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+ {
+ puts ("read succeeded");
+ return (void *) 1l;
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ void *r;
+ struct sigaction sa;
+
+ sa.sa_handler = SIG_IGN;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction (SIGPIPE, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ return 1;
+ }
+
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ /* This will cause the read in the child to return. */
+ close (fd[0]);
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("result is wrong");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel6.c b/test/nptl/tst-cancel6.c
new file mode 100644
index 000000000..94de85830
--- /dev/null
+++ b/test/nptl/tst-cancel6.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2002 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. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ char buf[100];
+ fgets (buf, sizeof (buf), arg);
+ /* This call should never return. */
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ return 1;
+ }
+
+ FILE *fp = fdopen (fd[0], "r");
+ if (fp == NULL)
+ {
+ puts ("fdopen failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, fp) != 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;
+ }
+
+ return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cancel9.c b/test/nptl/tst-cancel9.c
new file mode 100644
index 000000000..037ef30fd
--- /dev/null
+++ b/test/nptl/tst-cancel9.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2003, 2004 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 <fcntl.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+static void
+cleanup (void *arg)
+{
+ fputs ("in cleanup\n", stdout);
+}
+
+
+static void *
+tf (void *arg)
+{
+ int fd = open ("/dev/null", O_RDWR);
+ if (fd == -1)
+ {
+ puts ("cannot open /dev/null");
+ exit (1);
+ }
+ FILE *fp = fdopen (fd, "w");
+ if (fp == NULL)
+ {
+ puts ("fdopen failed");
+ exit (1);
+ }
+
+ pthread_cleanup_push (cleanup, NULL);
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ while (1)
+ /* fprintf() uses write() which is a cancallation point. */
+ fprintf (fp, "foo");
+
+ pthread_cleanup_pop (0);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, 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");
+ exit (1);
+ }
+
+ sleep (1);
+
+ puts ("cancel now");
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ puts ("waiting for the child");
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread wasn't canceled");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cleanup4.c b/test/nptl/tst-cleanup4.c
new file mode 100644
index 000000000..1489fd31b
--- /dev/null
+++ b/test/nptl/tst-cleanup4.c
@@ -0,0 +1,198 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* LinuxThreads pthread_cleanup_{push,pop} helpers. */
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+ void (*__routine) (void *),
+ void *__arg);
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+ int __execute);
+
+static int fds[2];
+static pthread_barrier_t b2;
+static int global;
+
+/* Defined in tst-cleanup4aux.c, never compiled with -fexceptions. */
+extern void fn5 (void);
+extern void fn7 (void);
+extern void fn9 (void);
+
+void
+clh (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("clh (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static __attribute__((noinline)) void
+fn_read (void)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ char c;
+ read (fds[0], &c, 1);
+}
+
+
+__attribute__((noinline)) void
+fn0 (void)
+{
+ pthread_cleanup_push (clh, (void *) 1l);
+
+ fn_read ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+__attribute__((noinline)) void
+fn1 (void)
+{
+ /* This is the old LinuxThreads pthread_cleanup_{push,pop}. */
+ struct _pthread_cleanup_buffer b;
+ _pthread_cleanup_push (&b, clh, (void *) 2l);
+
+ fn0 ();
+
+ _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn2 (void)
+{
+ pthread_cleanup_push (clh, (void *) 3l);
+
+ fn1 ();
+
+ pthread_cleanup_pop (1);
+}
+
+
+static void *
+tf (void *a)
+{
+ switch ((long) a)
+ {
+ case 0:
+ fn2 ();
+ break;
+ case 1:
+ fn5 ();
+ break;
+ case 2:
+ fn7 ();
+ break;
+ case 3:
+ fn9 ();
+ break;
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ int result = 0;
+
+ if (pipe (fds) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("b2 init failed");
+ exit (1);
+ }
+
+ const int expect[] =
+ {
+ 15, /* 1 2 3 */
+ 276, /* 1 4 5 6 */
+ 120, /* 1 7 8 */
+ 460 /* 1 2 9 10 */
+ };
+
+ long i;
+ for (i = 0; i < 4; ++i)
+ {
+ global = 0;
+
+ printf ("test %ld\n", i);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) i) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cancel (th);
+
+ void *r;
+ if ((e = pthread_join (th, &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ if (global != expect[i])
+ {
+ printf ("global = %d, expected %d\n", global, expect[i]);
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-join5.c b/test/nptl/tst-join5.c
new file mode 100644
index 000000000..b08af6e43
--- /dev/null
+++ b/test/nptl/tst-join5.c
@@ -0,0 +1,143 @@
+/* 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>
+
+
+static void *
+tf1 (void *arg)
+{
+ pthread_join ((pthread_t) arg, NULL);
+
+ puts ("1st join returned");
+
+ return (void *) 1l;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ int a;
+ a = pthread_join ((pthread_t) arg, NULL);
+
+ puts ("2nd join returned");
+ printf("a = %i\n", a);
+
+ return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ int err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("1st circular join succeeded");
+ exit (1);
+ }
+ if (err != EDEADLK)
+ {
+ printf ("1st circular join %d, not EDEADLK\n", err);
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel 1st thread");
+ exit (1);
+ }
+
+ void *r;
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ printf ("cannot join 1st thread: %d\n", err);
+ exit (1);
+ }
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("1st thread not canceled");
+ exit (1);
+ }
+
+ err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("2nd circular join succeeded");
+ exit (1);
+ }
+ if (err != EDEADLK)
+ {
+ printf ("2nd circular join %d, not EDEADLK\n", err);
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel 2nd thread");
+ exit (1);
+ }
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("cannot join 2nd thread");
+ exit (1);
+ }
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("2nd thread not canceled");
+ exit (1);
+ }
+
+ err = pthread_join (pthread_self (), NULL);
+ if (err == 0)
+ {
+ puts ("2nd circular join succeeded");
+ exit (1);
+ }
+ if (err != EDEADLK)
+ {
+ printf ("2nd circular join %d, not EDEADLK\n", err);
+ exit (1);
+ }
+
+ exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-key3.c b/test/nptl/tst-key3.c
new file mode 100644
index 000000000..73cb7417a
--- /dev/null
+++ b/test/nptl/tst-key3.c
@@ -0,0 +1,156 @@
+/* Copyright (C) 2002 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. */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define N 2
+
+
+static int cnt0;
+static void
+f0 (void *p)
+{
+ ++cnt0;
+}
+
+
+static int cnt1;
+static void
+f1 (void *p)
+{
+ ++cnt1;
+}
+
+
+static void (*fcts[N]) (void *) =
+{
+ f0,
+ f1
+};
+
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_key_t *key = (pthread_key_t *) arg;
+
+ if (pthread_setspecific (*key, (void *) -1l) != 0)
+ {
+ write (2, "setspecific failed\n", 19);
+ _exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ const struct timespec t = { .tv_sec = 1000, .tv_nsec = 0 };
+ while (1)
+ nanosleep (&t, NULL);
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_key_t keys[N];
+
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_key_create (&keys[i], fcts[i]) != 0)
+ {
+ write (2, "key_create failed\n", 18);
+ _exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ write (2, "barrier_init failed\n", 20);
+ _exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ if (pthread_cancel (th) != 0)
+ {
+ write (2, "cancel failed\n", 14);
+ _exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ write (2, "join failed\n", 12);
+ _exit (1);
+ }
+
+ if (status != PTHREAD_CANCELED)
+ {
+ write (2, "thread not canceled\n", 20);
+ _exit (1);
+ }
+
+ /* Note that the TSD destructors not necessarily have to have
+ finished by the time pthread_join returns. At least according to
+ POSIX. We implement the stronger requirement that they indeed
+ have run and therefore these tests succeed. */
+ if (cnt0 != 0)
+ {
+ write (2, "cnt0 != 0\n", 10);
+ _exit (1);
+ }
+
+ if (cnt1 != 1)
+ {
+ write (2, "cnt1 != 1\n", 10);
+ _exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_key_delete (keys[i]) != 0)
+ {
+ write (2, "key_delete failed\n", 18);
+ _exit (1);
+ }
+
+ if (pthread_barrier_destroy (&b) != 0)
+ {
+ write (2, "barrier_destroy failed\n", 23);
+ _exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"