diff options
author | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-14 02:24:00 +0000 |
---|---|---|
committer | "Steven J. Hill" <sjhill@realitydiluted.com> | 2006-02-14 02:24:00 +0000 |
commit | 0cb7f2febfc936afd3653cf5a1c6776c04ee83ce (patch) | |
tree | b2bd0d88fb64f77ae9be5fef564596b501a9580f | |
parent | c146e777742ef6a9736145332246b13c1480d8a1 (diff) | |
download | uClibc-alpine-0cb7f2febfc936afd3653cf5a1c6776c04ee83ce.tar.bz2 uClibc-alpine-0cb7f2febfc936afd3653cf5a1c6776c04ee83ce.tar.xz |
Another 11 tests pass with only 3 more to go. One of them uses a system call that I have not implemented cancellation points for and the other two should not take me long.
-rw-r--r-- | test/nptl/Makefile | 15 | ||||
-rw-r--r-- | test/nptl/tst-cancel11.c | 123 | ||||
-rw-r--r-- | test/nptl/tst-cancel2.c | 100 | ||||
-rw-r--r-- | test/nptl/tst-cancel20.c | 264 | ||||
-rw-r--r-- | test/nptl/tst-cancel21.c | 294 | ||||
-rw-r--r-- | test/nptl/tst-cancel22.c | 121 | ||||
-rw-r--r-- | test/nptl/tst-cancel3.c | 98 | ||||
-rw-r--r-- | test/nptl/tst-cancel6.c | 79 | ||||
-rw-r--r-- | test/nptl/tst-cancel9.c | 126 | ||||
-rw-r--r-- | test/nptl/tst-cleanup4.c | 198 | ||||
-rw-r--r-- | test/nptl/tst-join5.c | 143 | ||||
-rw-r--r-- | test/nptl/tst-key3.c | 156 |
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" |