diff options
Diffstat (limited to 'nptl/tst-join5.c')
-rw-r--r-- | nptl/tst-join5.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/nptl/tst-join5.c b/nptl/tst-join5.c index 589fac6b5f..db005f5b71 100644 --- a/nptl/tst-join5.c +++ b/nptl/tst-join5.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. +/* Copyright (C) 2003, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. @@ -21,120 +21,187 @@ #include <pthread.h> #include <stdio.h> #include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <sys/syscall.h> + + +#define wait_code() \ + do { \ + struct timespec ts = { .tv_sec = 0, .tv_nsec = 200000000 }; \ + while (syscall (__NR_nanosleep, &ts, &ts) < 0) \ + /* nothing */; \ + } while (0) + + +#ifdef WAIT_IN_CHILD +static pthread_barrier_t b; +#endif static void * tf1 (void *arg) { - pthread_join ((pthread_t) arg, NULL); +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + exit (1); + } - puts ("1st join returned"); + wait_code (); +#endif - return (void *) 1l; + pthread_join ((pthread_t) arg, NULL); + + exit (42); } static void * tf2 (void *arg) { - pthread_join ((pthread_t) arg, NULL); +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + exit (1); + } - puts ("2nd join returned"); + wait_code (); +#endif + pthread_join ((pthread_t) arg, NULL); - return (void *) 1l; + exit (43); } static int do_test (void) { +#ifdef WAIT_IN_CHILD + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } +#endif + pthread_t th; int err = pthread_join (pthread_self (), NULL); if (err == 0) { puts ("1st circular join succeeded"); - exit (1); + return 1; } if (err != EDEADLK) { printf ("1st circular join %d, not EDEADLK\n", err); - exit (1); + return 1; } if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0) { puts ("1st create failed"); - exit (1); + return 1; } +#ifndef WAIT_IN_CHILD + wait_code (); +#endif + if (pthread_cancel (th) != 0) { puts ("cannot cancel 1st thread"); - exit (1); + return 1; + } + +#ifdef WAIT_IN_CHILD + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + return 1; } +#endif void *r; err = pthread_join (th, &r); if (err != 0) { printf ("cannot join 1st thread: %d\n", err); - exit (1); + return 1; } if (r != PTHREAD_CANCELED) { puts ("1st thread not canceled"); - exit (1); + return 1; } err = pthread_join (pthread_self (), NULL); if (err == 0) { puts ("2nd circular join succeeded"); - exit (1); + return 1; } if (err != EDEADLK) { printf ("2nd circular join %d, not EDEADLK\n", err); - exit (1); + return 1; } if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0) { puts ("2nd create failed"); - exit (1); + return 1; } +#ifndef WAIT_IN_CHILD + wait_code (); +#endif + if (pthread_cancel (th) != 0) { puts ("cannot cancel 2nd thread"); - exit (1); + return 1; } +#ifdef WAIT_IN_CHILD + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __func__); + return 1; + } +#endif + if (pthread_join (th, &r) != 0) { puts ("cannot join 2nd thread"); - exit (1); + return 1; } if (r != PTHREAD_CANCELED) { puts ("2nd thread not canceled"); - exit (1); + return 1; } err = pthread_join (pthread_self (), NULL); if (err == 0) { - puts ("2nd circular join succeeded"); - exit (1); + puts ("3rd circular join succeeded"); + return 1; } if (err != EDEADLK) { - printf ("2nd circular join %d, not EDEADLK\n", err); - exit (1); + printf ("3rd circular join %d, not EDEADLK\n", err); + return 1; } - exit (0); + return 0; } #define TEST_FUNCTION do_test () |