summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/nptl/tst-cleanup1.c100
-rw-r--r--test/nptl/tst-cleanup2.c63
-rw-r--r--test/nptl/tst-cleanup3.c98
-rw-r--r--test/nptl/tst-cond1.c94
-rw-r--r--test/nptl/tst-cond10.c173
-rw-r--r--test/nptl/tst-cond11.c191
-rw-r--r--test/nptl/tst-cond12.c196
-rw-r--r--test/nptl/tst-cond13.c2
-rw-r--r--test/nptl/tst-cond14.c118
-rw-r--r--test/nptl/tst-cond15.c160
-rw-r--r--test/nptl/tst-cond16.c105
-rw-r--r--test/nptl/tst-cond17.c2
-rw-r--r--test/nptl/tst-cond18.c117
-rw-r--r--test/nptl/tst-cond19.c76
-rw-r--r--test/nptl/tst-cond2.c163
-rw-r--r--test/nptl/tst-cond20.c170
-rw-r--r--test/nptl/tst-cond21.c3
-rw-r--r--test/nptl/tst-cond3.c113
-rw-r--r--test/nptl/tst-cond4.c264
-rw-r--r--test/nptl/tst-cond5.c106
-rw-r--r--test/nptl/tst-cond6.c234
-rw-r--r--test/nptl/tst-cond7.c168
-rw-r--r--test/nptl/tst-cond8.c277
-rw-r--r--test/nptl/tst-cond9.c150
-rw-r--r--test/nptl/tst-detach1.c56
-rw-r--r--test/nptl/tst-eintr1.c105
-rw-r--r--test/nptl/tst-eintr2.c118
-rw-r--r--test/nptl/tst-eintr3.c72
-rw-r--r--test/nptl/tst-eintr4.c56
-rw-r--r--test/nptl/tst-eintr5.c81
-rw-r--r--test/nptl/tst-exec2.c154
-rw-r--r--test/nptl/tst-exec3.c152
-rw-r--r--test/nptl/tst-exec4.c116
-rw-r--r--test/nptl/tst-flock1.c93
-rw-r--r--test/nptl/tst-flock2.c260
-rw-r--r--test/nptl/tst-initializers1.c48
-rw-r--r--test/nptl/tst-key1.c89
-rw-r--r--test/nptl/tst-key2.c115
-rw-r--r--test/nptl/tst-key4.c137
-rw-r--r--test/nptl/tst-kill1.c100
-rw-r--r--test/nptl/tst-kill2.c139
-rw-r--r--test/nptl/tst-kill3.c159
-rw-r--r--test/nptl/tst-kill4.c74
-rw-r--r--test/nptl/tst-kill5.c49
-rw-r--r--test/nptl/tst-kill6.c162
-rw-r--r--test/nptl/tst-once1.c51
-rw-r--r--test/nptl/tst-once2.c104
-rw-r--r--test/nptl/tst-once3.c162
-rw-r--r--test/nptl/tst-once4.c202
-rw-r--r--test/nptl/tst-popen1.c60
-rw-r--r--test/nptl/tst-rwlock1.c117
-rw-r--r--test/nptl/tst-rwlock10.c21
-rw-r--r--test/nptl/tst-rwlock11.c21
-rw-r--r--test/nptl/tst-rwlock12.c208
-rw-r--r--test/nptl/tst-rwlock13.c71
-rw-r--r--test/nptl/tst-rwlock14.c169
-rw-r--r--test/nptl/tst-rwlock2.c143
-rw-r--r--test/nptl/tst-rwlock3.c93
-rw-r--r--test/nptl/tst-rwlock4.c190
-rw-r--r--test/nptl/tst-rwlock5.c87
-rw-r--r--test/nptl/tst-rwlock6.c226
-rw-r--r--test/nptl/tst-rwlock7.c179
-rw-r--r--test/nptl/tst-rwlock8.c164
-rw-r--r--test/nptl/tst-rwlock9.c203
-rw-r--r--test/nptl/tst-sched1.c98
-rw-r--r--test/nptl/tst-spin1.c57
-rw-r--r--test/nptl/tst-spin2.c159
-rw-r--r--test/nptl/tst-spin3.c55
-rw-r--r--test/nptl/tst-tsd1.c118
-rw-r--r--test/nptl/tst-tsd2.c97
-rw-r--r--test/nptl/tst-tsd3.c129
-rw-r--r--test/nptl/tst-tsd4.c103
72 files changed, 8765 insertions, 0 deletions
diff --git a/test/nptl/tst-cleanup1.c b/test/nptl/tst-cleanup1.c
new file mode 100644
index 000000000..2230e0fbe
--- /dev/null
+++ b/test/nptl/tst-cleanup1.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002, 2003 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 int global;
+
+
+static void
+ch (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("ch (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+ pthread_cancel (pthread_self ());
+
+ pthread_cleanup_push (ch, (void *) 1l);
+
+ pthread_cleanup_push (ch, (void *) 2l);
+
+ pthread_cleanup_push (ch, (void *) 3l);
+
+ pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ void *r;
+ int e;
+ 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 != 9)
+ {
+ printf ("global = %d, expected 9\n", global);
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cleanup2.c b/test/nptl/tst-cleanup2.c
new file mode 100644
index 000000000..30e10b120
--- /dev/null
+++ b/test/nptl/tst-cleanup2.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Bao Duong <bduong@progress.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 <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+static sigjmp_buf jmpbuf;
+
+static void
+sig_handler (int signo)
+{
+ siglongjmp (jmpbuf, 1);
+}
+
+static int
+do_test (void)
+{
+ char *p = NULL;
+ struct sigaction sa;
+
+ sa.sa_handler = sig_handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction (SIGSEGV, &sa, 0))
+ {
+ perror ("installing SIGSEGV handler\n");
+ exit (1);
+ }
+
+ puts ("Attempting to sprintf to null ptr");
+ if (setjmp (jmpbuf))
+ {
+ puts ("Exiting main...");
+ return 0;
+ }
+
+ sprintf (p, "This should segv\n");
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cleanup3.c b/test/nptl/tst-cleanup3.c
new file mode 100644
index 000000000..c44277370
--- /dev/null
+++ b/test/nptl/tst-cleanup3.c
@@ -0,0 +1,98 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+ int val = (long int) arg;
+
+ printf ("ch (%d)\n", val);
+
+ global *= val;
+ global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+ pthread_cleanup_push (ch, (void *) 1l);
+
+ pthread_cleanup_push (ch, (void *) 2l);
+
+ pthread_cleanup_push (ch, (void *) 3l);
+
+ pthread_exit ((void *) 1l);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ pthread_cleanup_pop (1);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ void *r;
+ int e;
+ if ((e = pthread_join (th, &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+
+ if (r != (void *) 1l)
+ {
+ puts ("thread not canceled");
+ exit (1);
+ }
+
+ if (global != 9)
+ {
+ printf ("global = %d, expected 9\n", global);
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond1.c b/test/nptl/tst-cond1.c
new file mode 100644
index 000000000..46085c2b7
--- /dev/null
+++ b/test/nptl/tst-cond1.c
@@ -0,0 +1,94 @@
+/* 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 <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *p)
+{
+ int err;
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child: cannot get mutex");
+
+ puts ("child: got mutex; signalling");
+
+ pthread_cond_signal (&cond);
+
+ puts ("child: unlock");
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child: cannot unlock");
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ puts ("parent: get mutex");
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot get mutex");
+
+ puts ("parent: create child");
+
+ err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot create thread");
+
+ puts ("parent: wait for condition");
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: cannot wait fir signal");
+
+ puts ("parent: got signal");
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: failed to join");
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond10.c b/test/nptl/tst-cond10.c
new file mode 100644
index 000000000..34956d468
--- /dev/null
+++ b/test/nptl/tst-cond10.c
@@ -0,0 +1,173 @@
+/* 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 <error.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define N 10
+#define ROUNDS 100
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t bN1;
+static pthread_barrier_t b2;
+
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("child: 1st mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 1st barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&cond, &mut) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("child: mutex_unlock failed");
+ exit (1);
+ }
+
+ e = pthread_barrier_wait (&bN1);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: 2nd barrier_wait failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&bN1, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ int r;
+ for (r = 0; r < ROUNDS; ++r)
+ {
+ printf ("round %d\n", r + 1);
+
+ int i;
+ pthread_t th[N];
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_create (&th[i], &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b2);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: 1st barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ /* N single signal calls. Without locking. This tests that no
+ signal gets lost. */
+ for (i = 0; i < N; ++i)
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&bN1);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: 2nd barrier_wait failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond11.c b/test/nptl/tst-cond11.c
new file mode 100644
index 000000000..0de4d5613
--- /dev/null
+++ b/test/nptl/tst-cond11.c
@@ -0,0 +1,191 @@
+/* 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 <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
+run_test (clockid_t cl)
+{
+ pthread_condattr_t condattr;
+ pthread_cond_t cond;
+ pthread_mutexattr_t mutattr;
+ pthread_mutex_t mut;
+
+ printf ("clock = %d\n", (int) cl);
+
+ if (pthread_condattr_init (&condattr) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_setclock (&condattr, cl) != 0)
+ {
+ puts ("condattr_setclock failed");
+ return 1;
+ }
+
+ 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;
+ }
+
+ if (pthread_cond_init (&cond, &condattr) != 0)
+ {
+ puts ("cond_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_destroy (&condattr) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_init (&mutattr) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (&mut, &mutattr) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_destroy (&mutattr) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != EDEADLK)
+ {
+ puts ("2nd mutex_lock did not return EDEADLK");
+ return 1;
+ }
+
+ struct timespec ts;
+ if (clock_gettime (cl, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ /* Wait one second. */
+ ++ts.tv_sec;
+
+ int e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("cond_timedwait succeeded");
+ return 1;
+ }
+ else if (e != ETIMEDOUT)
+ {
+ puts ("cond_timedwait did not return ETIMEDOUT");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_destroy (&mut) != 0)
+ {
+ puts ("mutex_destroy failed");
+ return 1;
+ }
+
+ if (pthread_cond_destroy (&cond) != 0)
+ {
+ puts ("cond_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 TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond12.c b/test/nptl/tst-cond12.c
new file mode 100644
index 000000000..03e4881c9
--- /dev/null
+++ b/test/nptl/tst-cond12.c
@@ -0,0 +1,196 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static char fname[] = "/tmp/tst-cond12-XXXXXX";
+static int fd;
+
+
+static void prepare (void);
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+
+static void
+prepare (void)
+{
+ fd = mkstemp (fname);
+ if (fd == -1)
+ {
+ printf ("mkstemp failed: %m\n");
+ exit (1);
+ }
+ add_temp_file (fname);
+ if (ftruncate (fd, 1000) < 0)
+ {
+ printf ("ftruncate failed: %m\n");
+ exit (1);
+ }
+}
+
+
+static int
+do_test (void)
+{
+ struct
+ {
+ pthread_mutex_t m;
+ pthread_cond_t c;
+ int var;
+ } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED)
+ {
+ printf ("initial mmap failed: %m\n");
+ return 1;
+ }
+
+ pthread_mutexattr_t ma;
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_setpshared (&ma, 1) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+ if (pthread_mutex_init (&p->m, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+ if (pthread_mutexattr_destroy (&ma) != 0)
+ {
+ puts ("mutexattr_destroy failed");
+ return 1;
+ }
+
+ pthread_condattr_t ca;
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+ if (pthread_condattr_setpshared (&ca, 1) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ return 1;
+ }
+ if (pthread_cond_init (&p->c, &ca) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+ if (pthread_condattr_destroy (&ca) != 0)
+ {
+ puts ("condattr_destroy failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&p->m) != 0)
+ {
+ puts ("initial mutex_lock failed");
+ return 1;
+ }
+
+ p->var = 42;
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ printf ("fork failed: %m\n");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ void *oldp = p;
+ p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+ if (p == oldp)
+ {
+ puts ("child: mapped to same address");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ munmap (oldp, sizeof (*p));
+
+ if (pthread_mutex_lock (&p->m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ p->var = 0;
+
+#ifndef USE_COND_SIGNAL
+ if (pthread_cond_broadcast (&p->c) != 0)
+ {
+ puts ("child: cond_broadcast failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+#else
+ if (pthread_cond_signal (&p->c) != 0)
+ {
+ puts ("child: cond_signal failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+#endif
+
+ if (pthread_mutex_unlock (&p->m) != 0)
+ {
+ puts ("child: mutex_unlock failed");
+ kill (getppid (), SIGKILL);
+ exit (1);
+ }
+
+ exit (0);
+ }
+
+ do
+ pthread_cond_wait (&p->c, &p->m);
+ while (p->var != 0);
+
+ if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
+ {
+ printf ("waitpid failed: %m\n");
+ kill (pid, SIGKILL);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/test/nptl/tst-cond13.c b/test/nptl/tst-cond13.c
new file mode 100644
index 000000000..29d79b533
--- /dev/null
+++ b/test/nptl/tst-cond13.c
@@ -0,0 +1,2 @@
+#define USE_COND_SIGNAL 1
+#include "tst-cond12.c"
diff --git a/test/nptl/tst-cond14.c b/test/nptl/tst-cond14.c
new file mode 100644
index 000000000..106fa8c21
--- /dev/null
+++ b/test/nptl/tst-cond14.c
@@ -0,0 +1,118 @@
+/* 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 <string.h>
+#include <unistd.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut2) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&cond, &mut) != 0)
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("parent: create child");
+
+ pthread_t th;
+ int err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("parent: cannot create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* We have to synchronize with the child. */
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+
+ /* Give the child to reach to pthread_cond_wait. */
+ sleep (1);
+
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 3
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond15.c b/test/nptl/tst-cond15.c
new file mode 100644
index 000000000..e815e253b
--- /dev/null
+++ b/test/nptl/tst-cond15.c
@@ -0,0 +1,160 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_lock failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut2) != 0)
+ {
+ printf ("%s: mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += p == NULL ? 100 : 1;
+
+ int err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if ((err != 0 && p == NULL) || (err != ETIMEDOUT && p != NULL))
+ {
+ printf ("%s: cond_wait failed\n", __func__);
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 1st mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 2nd mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ printf ("%s: 3rd mutex_unlock failed\n", __func__);
+ exit (1);
+ }
+
+ puts ("child: done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("parent: create 1st child");
+
+ pthread_t th;
+ int err = pthread_create (&th, NULL, tf, NULL);
+ if (err != 0)
+ {
+ printf ("parent: cannot 1st create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* We have to synchronize with the child. */
+ if (pthread_mutex_lock (&mut2) != 0)
+ {
+ puts ("2nd mutex_lock failed");
+ return 1;
+ }
+
+ /* Give the child to reach to pthread_cond_wait. */
+ sleep (1);
+
+ if (pthread_cond_signal (&cond) != 0)
+ {
+ puts ("cond_signal failed");
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+
+ puts ("parent: create 2nd child");
+
+ err = pthread_create (&th, NULL, tf, (void *) 1l);
+ if (err != 0)
+ {
+ printf ("parent: cannot 2nd create thread: %s\n", strerror (err));
+ return 1;
+ }
+
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("parent: failed to join: %s\n", strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 6
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond16.c b/test/nptl/tst-cond16.c
new file mode 100644
index 000000000..00c27eced
--- /dev/null
+++ b/test/nptl/tst-cond16.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool n, exiting;
+FILE *f;
+int count;
+
+void *
+tf (void *dummy)
+{
+ bool loop = true;
+
+ while (loop)
+ {
+ pthread_mutex_lock (&lock);
+ while (n && !exiting)
+ pthread_cond_wait (&cv, &lock);
+ n = true;
+ pthread_mutex_unlock (&lock);
+
+ fputs (".", f);
+
+ pthread_mutex_lock (&lock);
+ n = false;
+ if (exiting)
+ loop = false;
+#ifdef UNLOCK_AFTER_BROADCAST
+ pthread_cond_broadcast (&cv);
+ pthread_mutex_unlock (&lock);
+#else
+ pthread_mutex_unlock (&lock);
+ pthread_cond_broadcast (&cv);
+#endif
+ }
+
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ f = fopen ("/dev/null", "w");
+ if (f == NULL)
+ {
+ printf ("couldn't open /dev/null, %m\n");
+ return 1;
+ }
+
+ count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 4;
+
+ pthread_t th[count];
+ int i, ret;
+ for (i = 0; i < count; ++i)
+ if ((ret = pthread_create (&th[i], NULL, tf, NULL)) != 0)
+ {
+ errno = ret;
+ printf ("pthread_create %d failed: %m\n", i);
+ return 1;
+ }
+
+ struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+ while (nanosleep (&ts, &ts) != 0);
+
+ pthread_mutex_lock (&lock);
+ exiting = true;
+ pthread_mutex_unlock (&lock);
+
+ for (i = 0; i < count; ++i)
+ pthread_join (th[i], NULL);
+
+ fclose (f);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond17.c b/test/nptl/tst-cond17.c
new file mode 100644
index 000000000..0586fa59a
--- /dev/null
+++ b/test/nptl/tst-cond17.c
@@ -0,0 +1,2 @@
+#define UNLOCK_AFTER_BROADCAST 1
+#include "tst-cond16.c"
diff --git a/test/nptl/tst-cond18.c b/test/nptl/tst-cond18.c
new file mode 100644
index 000000000..9fd81d298
--- /dev/null
+++ b/test/nptl/tst-cond18.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool exiting;
+int fd, count, spins, nn;
+
+void *
+tf (void *id)
+{
+ pthread_mutex_lock (&lock);
+
+ if ((long) id == 0)
+ {
+ while (!exiting)
+ {
+ if ((spins++ % 1000) == 0)
+ write (fd, ".", 1);
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock);
+ int njobs = rand () % (count + 1);
+ nn = njobs;
+ if ((rand () % 30) == 0)
+ pthread_cond_broadcast (&cv);
+ else
+ while (njobs--)
+ pthread_cond_signal (&cv);
+ }
+
+ pthread_cond_broadcast (&cv);
+ }
+ else
+ {
+ while (!exiting)
+ {
+ while (!nn && !exiting)
+ pthread_cond_wait (&cv, &lock);
+ --nn;
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock);
+ }
+ }
+
+ pthread_mutex_unlock (&lock);
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ fd = open ("/dev/null", O_WRONLY);
+ if (fd < 0)
+ {
+ printf ("couldn't open /dev/null, %m\n");
+ return 1;
+ }
+
+ count = sysconf (_SC_NPROCESSORS_ONLN);
+ if (count <= 0)
+ count = 1;
+ count *= 8;
+
+ pthread_t th[count + 1];
+ int i, ret;
+
+ for (i = 0; i <= count; ++i)
+ if ((ret = pthread_create (&th[i], NULL, tf, (void *) (long) i)) != 0)
+ {
+ errno = ret;
+ printf ("pthread_create %d failed: %m\n", i);
+ return 1;
+ }
+
+ struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+ while (nanosleep (&ts, &ts) != 0);
+
+ pthread_mutex_lock (&lock);
+ exiting = true;
+ pthread_mutex_unlock (&lock);
+
+ for (i = 0; i < count; ++i)
+ pthread_join (th[i], NULL);
+
+ close (fd);
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond19.c b/test/nptl/tst-cond19.c
new file mode 100644
index 000000000..1c9bb7dd7
--- /dev/null
+++ b/test/nptl/tst-cond19.c
@@ -0,0 +1,76 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ struct timespec ts;
+
+ if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ ts.tv_nsec = -1;
+
+ int e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("first cond_timedwait did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first cond_timedwait did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = 2000000000;
+
+ e = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (e == 0)
+ {
+ puts ("second cond_timedwait did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second cond_timedwait did not return EINVAL");
+ result = 1;
+ }
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond2.c b/test/nptl/tst-cond2.c
new file mode 100644
index 000000000..36f0f2941
--- /dev/null
+++ b/test/nptl/tst-cond2.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 2002, 2003, 2004 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 <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *a)
+{
+ int i = (long int) a;
+ int err;
+
+ printf ("child %d: lock\n", i);
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "locking in child failed");
+
+ printf ("child %d: sync\n", i);
+
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ printf ("child %d: wait\n", i);
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child %d: failed to wait", i);
+
+ printf ("child %d: woken up\n", i);
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "child %d: unlock[2] failed", i);
+
+ printf ("child %d: done\n", i);
+
+ return NULL;
+}
+
+
+#define N 10
+
+
+static int
+do_test (void)
+{
+ pthread_t th[N];
+ int i;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < N; ++i)
+ {
+ printf ("create thread %d\n", i);
+
+ err = pthread_create (&th[i], &at, tf, (void *) (long int) i);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "cannot create thread %d", i);
+
+ printf ("wait for child %d\n", i);
+
+ /* Wait for the child to start up and get the mutex for the
+ conditional variable. */
+ int e = pthread_barrier_wait (&bar);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ puts ("get lock outselves");
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "mut locking failed");
+
+ puts ("broadcast");
+
+ /* Wake up all threads. */
+ err = pthread_cond_broadcast (&cond);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "parent: broadcast failed");
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "mut unlocking failed");
+
+ /* Join all threads. */
+ for (i = 0; i < N; ++i)
+ {
+ printf ("join thread %d\n", i);
+
+ err = pthread_join (th[i], NULL);
+ if (err != 0)
+ error (EXIT_FAILURE, err, "join of child %d failed", i);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond20.c b/test/nptl/tst-cond20.c
new file mode 100644
index 000000000..18918f32e
--- /dev/null
+++ b/test/nptl/tst-cond20.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@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 <string.h>
+#include <unistd.h>
+
+#define N 10
+#define ROUNDS 1000
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+static int count;
+
+static void *
+tf (void *p)
+{
+ int i;
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ pthread_mutex_lock (&mut);
+
+ if (++count == N)
+ pthread_cond_signal (&cond2);
+
+#ifdef TIMED
+ struct timeval tv;
+ gettimeofday (&tv, NULL);
+ struct timespec ts;
+ /* Wait three seconds. */
+ ts.tv_sec = tv.tv_sec + 3;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ pthread_cond_timedwait (&cond, &mut, &ts);
+#else
+ pthread_cond_wait (&cond, &mut);
+#endif
+
+ pthread_mutex_unlock (&mut);
+
+ int err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_mutex_lock (&mut);
+
+ int i, j, err;
+ pthread_t th[N];
+ for (i = 0; i < N; ++i)
+ if ((err = pthread_create (&th[i], NULL, tf, NULL)) != 0)
+ {
+ printf ("cannot create thread %d: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ for (i = 0; i < ROUNDS; ++i)
+ {
+ pthread_cond_wait (&cond2, &mut);
+
+ if (i & 1)
+ pthread_mutex_unlock (&mut);
+
+ if (i & 2)
+ pthread_cond_broadcast (&cond);
+ else if (i & 4)
+ for (j = 0; j < N; ++j)
+ pthread_cond_signal (&cond);
+ else
+ {
+ for (j = 0; j < (i / 8) % N; ++j)
+ pthread_cond_signal (&cond);
+ pthread_cond_broadcast (&cond);
+ }
+
+ if ((i & 1) == 0)
+ pthread_mutex_unlock (&mut);
+
+ err = pthread_cond_destroy (&cond);
+ if (err)
+ {
+ printf ("pthread_cond_destroy failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Now clobber the cond variable which has been successfully
+ destroyed above. */
+ memset (&cond, (char) i, sizeof (cond));
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: barrier_wait failed");
+ return 1;
+ }
+
+ pthread_mutex_lock (&mut);
+
+ err = pthread_barrier_wait (&b);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: barrier_wait failed");
+ return 1;
+ }
+
+ count = 0;
+ err = pthread_cond_init (&cond, NULL);
+ if (err)
+ {
+ printf ("pthread_cond_init failed: %s\n", strerror (err));
+ return 1;
+ }
+ }
+
+ for (i = 0; i < N; ++i)
+ if ((err = pthread_join (th[i], NULL)) != 0)
+ {
+ printf ("failed to join thread %d: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond21.c b/test/nptl/tst-cond21.c
new file mode 100644
index 000000000..89cb771b5
--- /dev/null
+++ b/test/nptl/tst-cond21.c
@@ -0,0 +1,3 @@
+#include <sys/time.h>
+#define TIMED 1
+#include "tst-cond20.c"
diff --git a/test/nptl/tst-cond3.c b/test/nptl/tst-cond3.c
new file mode 100644
index 000000000..cb9eb8558
--- /dev/null
+++ b/test/nptl/tst-cond3.c
@@ -0,0 +1,113 @@
+/* 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 <string.h>
+#include <unistd.h>
+
+
+/* Note that this test requires more than the standard. It is
+ required that there are no spurious wakeups if only more readers
+ are added. This is a reasonable demand. */
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+#define N 10
+
+
+static void *
+tf (void *arg)
+{
+ int i = (long int) arg;
+ int err;
+
+ /* Get the mutex. */
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ printf ("child %d mutex_lock failed: %s\n", i, strerror (err));
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_cond_wait (&cond, &mut);
+
+ /* We should never get here. */
+ exit (1);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int err;
+ int i;
+
+ for (i = 0; i < N; ++i)
+ {
+ pthread_t th;
+
+ if (i != 0)
+ {
+ /* Release the mutex. */
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_unlock %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+ }
+
+ err = pthread_create (&th, NULL, tf, (void *) (long int) i);
+ if (err != 0)
+ {
+ printf ("create %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+
+ /* Get the mutex. */
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_lock %d failed: %s\n", i, strerror (err));
+ return 1;
+ }
+ }
+
+ /* Set an alarm for 1 second. The wrapper will expect this. */
+ alarm (1);
+
+ /* This call should never return. */
+ pthread_cond_wait (&cond, &mut);
+
+ puts ("cond_wait returned");
+ return 1;
+}
+
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond4.c b/test/nptl/tst-cond4.c
new file mode 100644
index 000000000..4d8859616
--- /dev/null
+++ b/test/nptl/tst-cond4.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <stdint.h>
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-cond4.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutexattr_t ma;
+ pthread_mutex_t *mut1;
+ pthread_mutex_t *mut2;
+ pthread_condattr_t ca;
+ pthread_cond_t *cond;
+ pid_t pid;
+ int result = 0;
+ int p;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+ + __alignof (pthread_mutex_t))
+ & ~(__alignof (pthread_mutex_t) - 1));
+ mut2 = mut1 + 1;
+
+ cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+ + __alignof (pthread_cond_t))
+ & ~(__alignof (pthread_cond_t) - 1));
+
+ condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+ & ~(__alignof (int) - 1));
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+ {
+ puts ("1st mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+ {
+ puts ("2nd mutexattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+ if (pthread_mutex_init (mut1, &ma) != 0)
+ {
+ puts ("1st mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (mut2, &ma) != 0)
+ {
+ puts ("2nd mutex_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ return 1;
+ }
+
+ if (pthread_condattr_getpshared (&ca, &p) != 0)
+ {
+ puts ("1st condattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default value for pshared in condattr wrong");
+ return 1;
+ }
+
+ if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_condattr_getpshared (&ca, &p) != 0)
+ {
+ puts ("2nd condattr_getpshared failed");
+ return 1;
+ }
+
+ if (p != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared condattr still not set");
+ return 1;
+ }
+
+ if (pthread_cond_init (cond, &ca) != 0)
+ {
+ puts ("cond_init failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 1st mutex_lock failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_unlock (mut1) != 0)
+ {
+ puts ("child: 1st mutex_unlock failed");
+ return 1;
+ }
+
+ do
+ if (pthread_cond_wait (cond, mut2) != 0)
+ {
+ puts ("child: cond_wait failed");
+ return 1;
+ }
+ while (*condition == 0);
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("child: 2nd mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ int status;
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 2nd mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("parent: 3rd mutex_lock failed");
+ return 1;
+ }
+
+ if (pthread_cond_signal (cond) != 0)
+ {
+ puts ("parent: cond_signal failed");
+ return 1;
+ }
+
+ *condition = 1;
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ return 1;
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, &status, 0);
+ result |= status;
+
+ puts ("parent done");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond5.c b/test/nptl/tst-cond5.c
new file mode 100644
index 000000000..efa207b5d
--- /dev/null
+++ b/test/nptl/tst-cond5.c
@@ -0,0 +1,106 @@
+/* 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 <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+static pthread_mutex_t mut;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+ pthread_mutexattr_t ma;
+ int err;
+ struct timespec ts;
+ struct timeval tv;
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+ {
+ puts ("mutexattr_settype failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (&mut, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ exit (1);
+ }
+
+ /* Get the mutex. */
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Waiting for the condition will fail. But we want the timeout here. */
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ exit (1);
+ }
+
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ /* This could in theory happen but here without any signal and
+ additional waiter it should not. */
+ puts ("cond_timedwait succeeded");
+ exit (1);
+ }
+ else if (err != ETIMEDOUT)
+ {
+ printf ("cond_timedwait returned with %s\n", strerror (err));
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ printf ("mutex_unlock failed: %s\n", strerror (err));
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond6.c b/test/nptl/tst-cond6.c
new file mode 100644
index 000000000..8c5fe2093
--- /dev/null
+++ b/test/nptl/tst-cond6.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <stdint.h>
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-cond6.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutexattr_t ma;
+ pthread_mutex_t *mut1;
+ pthread_mutex_t *mut2;
+ pthread_condattr_t ca;
+ pthread_cond_t *cond;
+ pid_t pid;
+ int result = 0;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ exit (1);
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ exit (1);
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ exit (1);
+ }
+
+ mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+ + __alignof (pthread_mutex_t))
+ & ~(__alignof (pthread_mutex_t) - 1));
+ mut2 = mut1 + 1;
+
+ cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+ + __alignof (pthread_cond_t))
+ & ~(__alignof (pthread_cond_t) - 1));
+
+ condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+ & ~(__alignof (int) - 1));
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("mutexattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (mut1, &ma) != 0)
+ {
+ puts ("1st mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (mut2, &ma) != 0)
+ {
+ puts ("2nd mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_condattr_init (&ca) != 0)
+ {
+ puts ("condattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("condattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_cond_init (cond, &ca) != 0)
+ {
+ puts ("cond_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 1st mutex_lock failed");
+ exit (1);
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+ else if (pid == 0)
+ {
+ struct timespec ts;
+ struct timeval tv;
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (mut1) != 0)
+ {
+ puts ("child: 1st mutex_unlock failed");
+ exit (1);
+ }
+
+ if (gettimeofday (&tv, NULL) != 0)
+ {
+ puts ("gettimeofday failed");
+ exit (1);
+ }
+
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 500000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ do
+ if (pthread_cond_timedwait (cond, mut2, &ts) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+ while (*condition == 0);
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("child: 2nd mutex_unlock failed");
+ exit (1);
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ int status;
+
+ if (pthread_mutex_lock (mut1) != 0)
+ {
+ puts ("parent: 2nd mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (mut2) != 0)
+ {
+ puts ("parent: 3rd mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_cond_signal (cond) != 0)
+ {
+ puts ("parent: cond_signal failed");
+ exit (1);
+ }
+
+ *condition = 1;
+
+ if (pthread_mutex_unlock (mut2) != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, &status, 0);
+ result |= status;
+
+ puts ("parent done");
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond7.c b/test/nptl/tst-cond7.c
new file mode 100644
index 000000000..5ab7b8f8f
--- /dev/null
+++ b/test/nptl/tst-cond7.c
@@ -0,0 +1,168 @@
+/* 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 <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+typedef struct
+ {
+ pthread_cond_t cond;
+ pthread_mutex_t lock;
+ pthread_t h;
+ } T;
+
+
+static volatile bool done;
+
+
+static void *
+tf (void *arg)
+{
+ puts ("child created");
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ T *t = (T *) arg;
+
+ if (pthread_mutex_lock (&t->lock) != 0)
+ {
+ puts ("child: lock failed");
+ exit (1);
+ }
+
+ done = true;
+
+ if (pthread_cond_signal (&t->cond) != 0)
+ {
+ puts ("child: cond_signal failed");
+ exit (1);
+ }
+
+ if (pthread_cond_wait (&t->cond, &t->lock) != 0)
+ {
+ puts ("child: cond_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&t->lock) != 0)
+ {
+ puts ("child: unlock failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int i;
+#define N 100
+ T *t[N];
+ for (i = 0; i < N; ++i)
+ {
+ printf ("round %d\n", i);
+
+ t[i] = (T *) malloc (sizeof (T));
+ if (t[i] == NULL)
+ {
+ puts ("out of memory");
+ exit (1);
+ }
+
+ if (pthread_mutex_init (&t[i]->lock, NULL) != 0
+ || pthread_cond_init (&t[i]->cond, NULL) != 0)
+ {
+ puts ("an _init function failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&t[i]->lock) != 0)
+ {
+ puts ("initial mutex_lock failed");
+ exit (1);
+ }
+
+ done = false;
+
+ if (pthread_create (&t[i]->h, NULL, tf, t[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ do
+ if (pthread_cond_wait (&t[i]->cond, &t[i]->lock) != 0)
+ {
+ puts ("cond_wait failed");
+ exit (1);
+ }
+ while (! done);
+
+ /* Release the lock since the cancel handler will get it. */
+ if (pthread_mutex_unlock (&t[i]->lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (t[i]->h) != 0)
+ {
+ puts ("cancel failed");
+ exit (1);
+ }
+
+ puts ("parent: joining now");
+
+ void *result;
+ if (pthread_join (t[i]->h, &result) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("result != PTHREAD_CANCELED");
+ exit (1);
+ }
+ }
+
+ for (i = 0; i < N; ++i)
+ free (t[i]);
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond8.c b/test/nptl/tst-cond8.c
new file mode 100644
index 000000000..9c97a96fa
--- /dev/null
+++ b/test/nptl/tst-cond8.c
@@ -0,0 +1,277 @@
+/* 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 <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+static pthread_barrier_t bar;
+
+
+static void
+ch (void *arg)
+{
+ int e = pthread_mutex_lock (&mut);
+ if (e == 0)
+ {
+ puts ("mutex not locked at all by cond_wait");
+ exit (1);
+ }
+
+ if (e != EDEADLK)
+ {
+ puts ("no deadlock error signaled");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("ch: cannot unlock mutex");
+ exit (1);
+ }
+
+ puts ("ch done");
+}
+
+
+static void *
+tf1 (void *p)
+{
+ int err;
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("child: cannot get mutex");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier_wait returned %d\n", err);
+ exit (1);
+ }
+
+ puts ("child: got mutex; waiting");
+
+ pthread_cleanup_push (ch, NULL);
+
+ pthread_cond_wait (&cond, &mut);
+
+ pthread_cleanup_pop (0);
+
+ puts ("child: cond_wait should not have returned");
+
+ return NULL;
+}
+
+
+static void *
+tf2 (void *p)
+{
+ int err;
+
+ if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+ || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+ {
+ puts ("cannot set cancellation options");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("child: cannot get mutex");
+ exit (1);
+ }
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("barrier_wait returned %d\n", err);
+ exit (1);
+ }
+
+ puts ("child: got mutex; waiting");
+
+ pthread_cleanup_push (ch, NULL);
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ pthread_cond_timedwait (&cond, &mut, &ts);
+
+ pthread_cleanup_pop (0);
+
+ puts ("child: cond_wait should not have returned");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ puts ("parent: get mutex");
+
+ err = pthread_barrier_init (&bar, NULL, 2);
+ if (err != 0)
+ {
+ puts ("parent: cannot init barrier");
+ exit (1);
+ }
+
+ puts ("parent: create child");
+
+ err = pthread_create (&th, NULL, tf1, NULL);
+ if (err != 0)
+ {
+ puts ("parent: cannot create thread");
+ exit (1);
+ }
+
+ puts ("parent: wait for child to lock mutex");
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: cannot wait for barrier");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel thread");
+ exit (1);
+ }
+
+ void *r;
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ puts ("parent: failed to join");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("child hasn't been canceled");
+ exit (1);
+ }
+
+
+
+ puts ("parent: create 2nd child");
+
+ err = pthread_create (&th, NULL, tf2, NULL);
+ if (err != 0)
+ {
+ puts ("parent: cannot create thread");
+ exit (1);
+ }
+
+ puts ("parent: wait for child to lock mutex");
+
+ err = pthread_barrier_wait (&bar);
+ if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("parent: cannot wait for barrier");
+ exit (1);
+ }
+
+ err = pthread_mutex_lock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ err = pthread_mutex_unlock (&mut);
+ if (err != 0)
+ {
+ puts ("parent: mutex_unlock failed");
+ exit (1);
+ }
+
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cannot cancel thread");
+ exit (1);
+ }
+
+ err = pthread_join (th, &r);
+ if (err != 0)
+ {
+ puts ("parent: failed to join");
+ exit (1);
+ }
+
+ if (r != PTHREAD_CANCELED)
+ {
+ puts ("child hasn't been canceled");
+ exit (1);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-cond9.c b/test/nptl/tst-cond9.c
new file mode 100644
index 000000000..2a8477dd8
--- /dev/null
+++ b/test/nptl/tst-cond9.c
@@ -0,0 +1,150 @@
+/* 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 <sys/time.h>
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+
+static void *
+tf (void *arg)
+{
+ int err = pthread_cond_wait (&cond, &mut);
+ if (err == 0)
+ {
+ puts ("cond_wait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_wait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ puts ("cond_timedwait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_timedwait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+ return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ int err;
+
+ printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+ err = pthread_cond_wait (&cond, &mut);
+ if (err == 0)
+ {
+ puts ("cond_wait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_wait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+
+ /* Current time. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ /* +1000 seconds in correct format. */
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 1000;
+
+ err = pthread_cond_timedwait (&cond, &mut, &ts);
+ if (err == 0)
+ {
+ puts ("cond_timedwait did not fail");
+ exit (1);
+ }
+
+ if (err != EPERM)
+ {
+ printf ("cond_timedwait didn't return EPERM but %d\n", err);
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("parent: mutex_lock failed");
+ exit (1);
+ }
+
+ puts ("creating thread");
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != (void *) 1l)
+ {
+ puts ("thread has wrong return value");
+ exit (1);
+ }
+
+ puts ("done");
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-detach1.c b/test/nptl/tst-detach1.c
new file mode 100644
index 000000000..7b27f6ead
--- /dev/null
+++ b/test/nptl/tst-detach1.c
@@ -0,0 +1,56 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* Give the child a chance to finish. */
+ sleep (1);
+
+ if (pthread_detach (th) != 0)
+ {
+ puts ("detach failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-eintr1.c b/test/nptl/tst-eintr1.c
new file mode 100644
index 000000000..43a5df5b9
--- /dev/null
+++ b/test/nptl/tst-eintr1.c
@@ -0,0 +1,105 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eintr.c"
+
+
+static void *
+tf2 (void *arg)
+{
+ return arg;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+ while (1)
+ {
+ pthread_t th;
+
+ int e = pthread_create (&th, NULL, tf2, NULL);
+ if (e != 0)
+ {
+ if (e == EINTR)
+ {
+ puts ("pthread_create returned EINTR");
+ exit (1);
+ }
+
+ char buf[100];
+ printf ("tf1: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ e = pthread_join (th, NULL);
+ if (e != 0)
+ {
+ if (e == EINTR)
+ {
+ puts ("pthread_join returned EINTR");
+ exit (1);
+ }
+
+ char buf[100];
+ printf ("tf1: pthread_join failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+ }
+}
+
+
+static int
+do_test (void)
+{
+ setup_eintr (SIGUSR1, NULL);
+
+ int i;
+ for (i = 0; i < 10; ++i)
+ {
+ pthread_t th;
+ int e = pthread_create (&th, NULL, tf1, NULL);
+ if (e != 0)
+ {
+ char buf[100];
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+ }
+
+ (void) tf1 (NULL);
+ /* NOTREACHED */
+
+ return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-eintr2.c b/test/nptl/tst-eintr2.c
new file mode 100644
index 000000000..8cbbc5a02
--- /dev/null
+++ b/test/nptl/tst-eintr2.c
@@ -0,0 +1,118 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf1 (void *arg)
+{
+ struct timespec ts;
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10000;
+
+ /* This call must never return. */
+ int e = pthread_mutex_timedlock (&m1, &ts);
+ char buf[100];
+ printf ("tf1: mutex_timedlock returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ while (1)
+ {
+ int e = pthread_mutex_lock (&m2);
+ if (e != 0)
+ {
+ puts ("tf2: mutex_lock failed");
+ exit (1);
+ }
+ e = pthread_mutex_unlock (&m2);
+ if (e != 0)
+ {
+ puts ("tf2: mutex_unlock failed");
+ exit (1);
+ }
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+ }
+}
+
+
+static int
+do_test (void)
+{
+ if (pthread_mutex_lock (&m1) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ setup_eintr (SIGUSR1, NULL);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf1, NULL);
+ if (e != 0)
+ {
+ printf ("main: 1st pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ e = pthread_create (&th, NULL, tf2, NULL);
+ if (e != 0)
+ {
+ printf ("main: 2nd pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ /* This call must never return. */
+ e = pthread_mutex_lock (&m1);
+ printf ("main: mutex_lock returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-eintr3.c b/test/nptl/tst-eintr3.c
new file mode 100644
index 000000000..eecab48b1
--- /dev/null
+++ b/test/nptl/tst-eintr3.c
@@ -0,0 +1,72 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eintr.c"
+
+
+static void *
+tf (void *arg)
+{
+ pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+ pthread_mutex_lock (&m);
+ /* This call must not return. */
+ pthread_mutex_lock (&m);
+
+ puts ("tf: mutex_lock returned");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t self = pthread_self ();
+
+ setup_eintr (SIGUSR1, &self);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ /* This call must never return. */
+ e = pthread_join (th, NULL);
+
+ if (e == EINTR)
+ puts ("pthread_join returned with EINTR");
+
+ return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-eintr4.c b/test/nptl/tst-eintr4.c
new file mode 100644
index 000000000..dffbdd605
--- /dev/null
+++ b/test/nptl/tst-eintr4.c
@@ -0,0 +1,56 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "eintr.c"
+
+
+static int
+do_test (void)
+{
+ pthread_t self = pthread_self ();
+
+ setup_eintr (SIGUSR1, &self);
+
+ pthread_barrier_t b;
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ /* This call must never return. */
+ int e = pthread_barrier_wait (&b);
+
+ if (e == EINTR)
+ puts ("pthread_join returned with EINTR");
+
+ return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-eintr5.c b/test/nptl/tst-eintr5.c
new file mode 100644
index 000000000..91473ec4c
--- /dev/null
+++ b/test/nptl/tst-eintr5.c
@@ -0,0 +1,81 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ struct timespec ts;
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10000;
+
+ /* This call must never return. */
+ int e = pthread_cond_timedwait (&c, &m, &ts);
+ char buf[100];
+ printf ("tf: cond_timedwait returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ setup_eintr (SIGUSR1, NULL);
+
+ pthread_t th;
+ char buf[100];
+ int e = pthread_create (&th, NULL, tf, NULL);
+ if (e != 0)
+ {
+ printf ("main: pthread_create failed: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+ exit (1);
+ }
+
+ /* This call must never return. */
+ e = pthread_cond_wait (&c, &m);
+ printf ("main: cond_wait returned: %s\n",
+ strerror_r (e, buf, sizeof (buf)));
+
+ return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-exec2.c b/test/nptl/tst-exec2.c
new file mode 100644
index 000000000..432da32ef
--- /dev/null
+++ b/test/nptl/tst-exec2.c
@@ -0,0 +1,154 @@
+/* Thread with running thread calls exec.
+ 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 <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void *
+tf (void *arg)
+{
+ pthread_t th = (pthread_t) arg;
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("thread in parent joined!?");
+ exit (1);
+ }
+
+ puts ("join in thread in parent returned!?");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ /* Not interested in knowing when the pipe is closed. */
+ if (sigignore (SIGPIPE) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Use the fd for stdout. This is kind of ugly because it
+ substitutes the fd of stdout but we know what we are doing
+ here... */
+ if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ {
+ puts ("dup2 failed");
+ exit (1);
+ }
+
+ close (fd[0]);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+ puts ("execl failed");
+ exit (1);
+ }
+
+ close (fd[1]);
+
+ char buf[200];
+ ssize_t n;
+ bool seen_pid = false;
+ while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+ {
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+
+ if (*endp != '\n')
+ {
+ printf ("didn't parse whole line: \"%s\"\n", buf);
+ exit (1);
+ }
+ if (endp == buf)
+ {
+ puts ("read empty line");
+ exit (1);
+ }
+
+ if (rpid != pid)
+ {
+ printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+ exit (1);
+ }
+
+ if (seen_pid)
+ {
+ puts ("found more than one PID line");
+ exit (1);
+ }
+ seen_pid = true;
+ }
+
+ close (fd[0]);
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!seen_pid)
+ {
+ puts ("didn't get PID");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-exec3.c b/test/nptl/tst-exec3.c
new file mode 100644
index 000000000..be49b048c
--- /dev/null
+++ b/test/nptl/tst-exec3.c
@@ -0,0 +1,152 @@
+/* Thread calls exec.
+ 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 <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static void *
+tf (void *arg)
+{
+ execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+ puts ("execl failed");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ int fd[2];
+ if (pipe (fd) != 0)
+ {
+ puts ("pipe failed");
+ exit (1);
+ }
+
+ /* Not interested in knowing when the pipe is closed. */
+ if (sigignore (SIGPIPE) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ /* Use the fd for stdout. This is kind of ugly because it
+ substitutes the fd of stdout but we know what we are doing
+ here... */
+ if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+ {
+ puts ("dup2 failed");
+ exit (1);
+ }
+
+ close (fd[0]);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("join succeeded!?");
+ exit (1);
+ }
+
+ puts ("join returned!?");
+ exit (1);
+ }
+
+ close (fd[1]);
+
+ char buf[200];
+ ssize_t n;
+ bool seen_pid = false;
+ while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+ {
+ /* We only expect to read the PID. */
+ char *endp;
+ long int rpid = strtol (buf, &endp, 10);
+
+ if (*endp != '\n')
+ {
+ printf ("didn't parse whole line: \"%s\"\n", buf);
+ exit (1);
+ }
+ if (endp == buf)
+ {
+ puts ("read empty line");
+ exit (1);
+ }
+
+ if (rpid != pid)
+ {
+ printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+ exit (1);
+ }
+
+ if (seen_pid)
+ {
+ puts ("found more than one PID line");
+ exit (1);
+ }
+ seen_pid = true;
+ }
+
+ close (fd[0]);
+
+ int status;
+ int err = waitpid (pid, &status, 0);
+ if (err != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (!seen_pid)
+ {
+ puts ("didn't get PID");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-exec4.c b/test/nptl/tst-exec4.c
new file mode 100644
index 000000000..b3920a030
--- /dev/null
+++ b/test/nptl/tst-exec4.c
@@ -0,0 +1,116 @@
+/* Signal handler and mask set in thread which calls exec.
+ 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 <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *arg)
+{
+ /* Ignore SIGUSR1 and block SIGUSR2. */
+ if (sigignore (SIGUSR1) != 0)
+ {
+ puts ("sigignore failed");
+ exit (1);
+ }
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR2);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("1st run: sigmask failed");
+ exit (1);
+ }
+
+ char **oldargv = (char **) arg;
+ size_t n = 1;
+ while (oldargv[n] != NULL)
+ ++n;
+
+ char **argv = (char **) alloca ((n + 1) * sizeof (char *));
+ for (n = 0; oldargv[n + 1] != NULL; ++n)
+ argv[n] = oldargv[n + 1];
+ argv[n++] = (char *) "--direct";
+ argv[n] = NULL;
+
+ execv (argv[0], argv);
+
+ puts ("execv failed");
+
+ exit (1);
+}
+
+
+static int
+do_test (int argc, char *argv[])
+{
+ if (argc == 1)
+ {
+ /* This is the second call. Perform the test. */
+ struct sigaction sa;
+
+ if (sigaction (SIGUSR1, NULL, &sa) != 0)
+ {
+ puts ("2nd run: sigaction failed");
+ return 1;
+ }
+ if (sa.sa_handler != SIG_IGN)
+ {
+ puts ("SIGUSR1 not ignored");
+ return 1;
+ }
+
+ sigset_t ss;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &ss) != 0)
+ {
+ puts ("2nd run: sigmask failed");
+ return 1;
+ }
+ if (! sigismember (&ss, SIGUSR2))
+ {
+ puts ("SIGUSR2 not blocked");
+ return 1;
+ }
+
+ return 0;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, argv) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_join (th, NULL);
+
+ puts ("join returned");
+
+ return 1;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-flock1.c b/test/nptl/tst-flock1.c
new file mode 100644
index 000000000..ed2472d3a
--- /dev/null
+++ b/test/nptl/tst-flock1.c
@@ -0,0 +1,93 @@
+/* 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>
+#include <sys/file.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+ if (flock (fd, LOCK_SH | LOCK_NB) != 0)
+ {
+ puts ("second flock failed");
+ exit (1);
+ }
+
+ pthread_mutex_unlock (&lock);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-flock1-XXXXXX";
+
+ fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ write (fd, "foobar xyzzy", 12);
+
+ if (flock (fd, LOCK_EX | LOCK_NB) != 0)
+ {
+ puts ("first flock failed");
+ exit (1);
+ }
+
+ pthread_mutex_lock (&lock);
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ pthread_mutex_lock (&lock);
+
+ void *result;
+ if (pthread_join (th, &result) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+
+ close (fd);
+
+ return result != NULL;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-flock2.c b/test/nptl/tst-flock2.c
new file mode 100644
index 000000000..8ef3206cc
--- /dev/null
+++ b/test/nptl/tst-flock2.c
@@ -0,0 +1,260 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 10
+ };
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("fourth fcntl failed");
+ exit (1);
+ }
+
+ pthread_mutex_unlock (&lock);
+
+ pthread_mutex_lock (&lock2);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-flock2-XXXXXX";
+
+ fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ return 1;
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ pthread_barrier_t *b;
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ return 1;
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ return 1;
+ }
+
+ struct flock fl =
+ {
+ .l_type = F_WRLCK,
+ .l_start = 0,
+ .l_whence = SEEK_SET,
+ .l_len = 10
+ };
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("first fcntl failed");
+ return 1;
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+
+ if (pid == 0)
+ {
+ /* Make sure the child does not stay around indefinitely. */
+ alarm (10);
+
+ /* Try to get the lock. */
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("child: second flock succeeded");
+ return 1;
+ }
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_UNLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("third fcntl failed");
+ return 1;
+ }
+ }
+
+ pthread_barrier_wait (b);
+
+ pthread_t th;
+ if (pid == 0)
+ {
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("1st locking of lock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&lock2) != 0)
+ {
+ puts ("1st locking of lock2 failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("2nd locking of lock failed");
+ return 1;
+ }
+
+ puts ("child locked file");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_WRLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("fifth fcntl succeeded");
+ return 1;
+ }
+
+ puts ("file locked by child");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid == 0)
+ {
+ if (pthread_mutex_unlock (&lock2) != 0)
+ {
+ puts ("unlock of lock2 failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ puts ("child's thread terminated");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid != 0)
+ {
+ fl.l_type = F_WRLCK;
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+ {
+ puts ("fifth fcntl succeeded");
+ return 1;
+ }
+
+ puts ("file still locked");
+ }
+
+ pthread_barrier_wait (b);
+
+ if (pid == 0)
+ {
+ _exit (0);
+ }
+
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ return 1;
+ }
+ puts ("child terminated");
+
+ if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+ {
+ puts ("sixth fcntl failed");
+ return 1;
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-initializers1.c b/test/nptl/tst-initializers1.c
new file mode 100644
index 000000000..ccd27286e
--- /dev/null
+++ b/test/nptl/tst-initializers1.c
@@ -0,0 +1,48 @@
+/* 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>
+
+pthread_mutex_t mtx_normal = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mtx_recursive = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_errorchk = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_adaptive = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+pthread_rwlock_t rwl_normal = PTHREAD_RWLOCK_INITIALIZER;
+pthread_rwlock_t rwl_writer
+ = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+int
+main (void)
+{
+ if (mtx_normal.__data.__kind != PTHREAD_MUTEX_TIMED_NP)
+ return 1;
+ if (mtx_recursive.__data.__kind != PTHREAD_MUTEX_RECURSIVE_NP)
+ return 1;
+ if (mtx_errorchk.__data.__kind != PTHREAD_MUTEX_ERRORCHECK_NP)
+ return 1;
+ if (mtx_adaptive.__data.__kind != PTHREAD_MUTEX_ADAPTIVE_NP)
+ return 1;
+ if (rwl_normal.__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
+ return 1;
+ if (rwl_writer.__data.__flags
+ != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
+ return 1;
+ return 0;
+}
diff --git a/test/nptl/tst-key1.c b/test/nptl/tst-key1.c
new file mode 100644
index 000000000..dfbe58417
--- /dev/null
+++ b/test/nptl/tst-key1.c
@@ -0,0 +1,89 @@
+/* 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 <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+ int max;
+#ifdef PTHREAD_KEYS_MAX
+ max = PTHREAD_KEYS_MAX;
+#else
+ max = _POSIX_THREAD_KEYS_MAX;
+#endif
+ pthread_key_t *keys = alloca (max * sizeof (pthread_key_t));
+
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ write (2, "key_create failed\n", 18);
+ _exit (1);
+ }
+ else
+ {
+ printf ("created key %d\n", i);
+
+ if (pthread_setspecific (keys[i], (const void *) (i + 100l)) != 0)
+ {
+ write (2, "setspecific failed\n", 19);
+ _exit (1);
+ }
+ }
+
+ for (i = 0; i < max; ++i)
+ {
+ if (pthread_getspecific (keys[i]) != (void *) (i + 100l))
+ {
+ write (2, "getspecific failed\n", 19);
+ _exit (1);
+ }
+
+ if (pthread_key_delete (keys[i]) != 0)
+ {
+ write (2, "key_delete failed\n", 18);
+ _exit (1);
+ }
+ }
+
+ /* Now it must be once again possible to allocate keys. */
+ if (pthread_key_create (&keys[0], NULL) != 0)
+ {
+ write (2, "2nd key_create failed\n", 22);
+ _exit (1);
+ }
+
+ if (pthread_key_delete (keys[0]) != 0)
+ {
+ write (2, "2nd key_delete failed\n", 22);
+ _exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-key2.c b/test/nptl/tst-key2.c
new file mode 100644
index 000000000..c5493322c
--- /dev/null
+++ b/test/nptl/tst-key2.c
@@ -0,0 +1,115 @@
+/* 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 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);
+ }
+
+ 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);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ write (2, "join failed\n", 12);
+ _exit (1);
+ }
+
+ 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);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-key4.c b/test/nptl/tst-key4.c
new file mode 100644
index 000000000..0a5b448e5
--- /dev/null
+++ b/test/nptl/tst-key4.c
@@ -0,0 +1,137 @@
+/* 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 <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#ifdef PTHREAD_KEYS_MAX
+const int max = PTHREAD_KEYS_MAX;
+#else
+const int max = _POSIX_THREAD_KEYS_MAX;
+#endif
+static pthread_key_t *keys;
+
+
+static void *
+tf1 (void *arg)
+{
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_setspecific (keys[i], (void *) (long int) (i + 1)) != 0)
+ {
+ puts ("setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_getspecific (keys[i]) != NULL)
+ {
+ printf ("getspecific for key %d not NULL\n", i);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ keys = alloca (max * sizeof (pthread_key_t));
+
+ int i;
+ for (i = 0; i < max; ++i)
+ if (pthread_key_create (&keys[i], NULL) != 0)
+ {
+ puts ("key_create failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (i = 0; i < 10; ++i)
+ {
+ int j;
+#define N 2
+ pthread_t th[N];
+ for (j = 0; j < N; ++j)
+ if (pthread_create (&th[j], NULL, tf1, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_create (&th[j], NULL, tf2, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < N; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill1.c b/test/nptl/tst-kill1.c
new file mode 100644
index 000000000..9eaf29be7
--- /dev/null
+++ b/test/nptl/tst-kill1.c
@@ -0,0 +1,100 @@
+/* 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 <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_cond_wait (&c, &m);
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it doesn't catch and which will
+ cause the process to terminate. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ /* This call should never return. */
+ pthread_join (th, NULL);
+
+ return 0;
+}
+
+
+#define EXPECTED_SIGNAL SIGUSR1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill2.c b/test/nptl/tst-kill2.c
new file mode 100644
index 000000000..1e3dc4104
--- /dev/null
+++ b/test/nptl/tst-kill2.c
@@ -0,0 +1,139 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+ /* Block SIGUSR1. */
+ sigset_t ss;
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* Compute timeout. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ /* Timeout: 1sec. */
+ ts.tv_sec += 1;
+
+ /* This call should never return. */
+ if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+ {
+ puts ("cond_timedwait didn't time out");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it has blocked. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != NULL)
+ {
+ puts ("return value wrong");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill3.c b/test/nptl/tst-kill3.c
new file mode 100644
index 000000000..9ea8d553b
--- /dev/null
+++ b/test/nptl/tst-kill3.c
@@ -0,0 +1,159 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+
+static void
+handler (int sig)
+{
+ write (1, "handler called\n", 15);
+ _exit (1);
+}
+
+
+static void *
+tf (void *a)
+{
+ /* Block SIGUSR1. */
+ sigset_t ss;
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ /* Compute timeout. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ /* Timeout: 1sec. */
+ ts.tv_sec += 1;
+
+ /* This call should never return. */
+ if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+ {
+ puts ("cond_timedwait didn't time out");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+
+ struct sigaction sa;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = handler;
+ if (sigaction (SIGUSR1, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ /* Send the thread a signal which it has blocked. */
+ if (pthread_kill (th, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+ if (r != NULL)
+ {
+ puts ("return value wrong");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill4.c b/test/nptl/tst-kill4.c
new file mode 100644
index 000000000..4e7ff5eaf
--- /dev/null
+++ b/test/nptl/tst-kill4.c
@@ -0,0 +1,74 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static void *
+tf (void *a)
+{
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ /* The following only works because we assume here something about
+ the implementation. Namely, that the memory allocated for the
+ thread descriptor is not going away, that the the TID field is
+ cleared and therefore the signal is sent to process 0, and that
+ we can savely assume there is no other process with this ID at
+ that time. */
+ int e = pthread_kill (th, 0);
+ if (e == 0)
+ {
+ puts ("pthread_kill succeeded");
+ exit (1);
+ }
+ if (e != ESRCH)
+ {
+ puts ("pthread_kill didn't return ESRCH");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill5.c b/test/nptl/tst-kill5.c
new file mode 100644
index 000000000..12560943c
--- /dev/null
+++ b/test/nptl/tst-kill5.c
@@ -0,0 +1,49 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int
+do_test (void)
+{
+ /* XXX This test might require architecture and system specific changes.
+ There is no guarantee that this signal number is invalid. */
+ int e = pthread_kill (pthread_self (), SIGRTMAX + 10);
+ if (e == 0)
+ {
+ puts ("kill didn't failed");
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("error not EINVAL");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-kill6.c b/test/nptl/tst-kill6.c
new file mode 100644
index 000000000..26e82d98f
--- /dev/null
+++ b/test/nptl/tst-kill6.c
@@ -0,0 +1,162 @@
+/* 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 <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_t receiver;
+static sem_t sem;
+static pthread_barrier_t b;
+
+static void
+handler (int sig)
+{
+ if (sig != SIGUSR1)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ if (pthread_self () != receiver)
+ {
+ write (STDOUT_FILENO, "not the intended receiver\n", 26);
+ _exit (1);
+ }
+
+ if (sem_post (&sem) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+static void *
+tf (void *a)
+{
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("child: barrier_wait failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+int
+do_test (void)
+{
+ struct sigaction sa;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = handler;
+ if (sigaction (SIGUSR1, &sa, NULL) != 0)
+ {
+ puts ("sigaction failed");
+ exit (1);
+ }
+
+#define N 20
+
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_attr_t a;
+
+ if (pthread_attr_init (&a) != 0)
+ {
+ puts ("attr_init failed");
+ exit (1);
+ }
+
+ if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ pthread_t th[N];
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ if (sem_init (&sem, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N * 10; ++i)
+ {
+ receiver = th[i % N];
+
+ if (pthread_kill (receiver, SIGUSR1) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+ }
+
+ int e = pthread_barrier_wait (&b);
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ exit (1);
+ }
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-once1.c b/test/nptl/tst-once1.c
new file mode 100644
index 000000000..87ed51c82
--- /dev/null
+++ b/test/nptl/tst-once1.c
@@ -0,0 +1,51 @@
+/* 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>
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+ ++global;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_once (&once, once_handler);
+ pthread_once (&once, once_handler);
+
+ if (global != 1)
+ {
+ printf ("global = %d, expected 1\n", global);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-once2.c b/test/nptl/tst-once2.c
new file mode 100644
index 000000000..c60634538
--- /dev/null
+++ b/test/nptl/tst-once2.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2002, 2004 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 <time.h>
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+ struct timespec ts;
+
+ ++global;
+
+ ts.tv_sec = 2;
+ ts.tv_nsec = 0;
+ nanosleep (&ts, NULL);
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_once (&once, once_handler);
+
+ if (global != 1)
+ {
+ printf ("thread %ld: global == %d\n", (long int) arg, global);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_attr_t at;
+ pthread_t th[N];
+ int cnt;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+ {
+ puts ("attr_setstacksize failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
+ {
+ printf ("creation of thread %d failed\n", cnt);
+ return 1;
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ for (cnt = 0; cnt < N; ++cnt)
+ if (pthread_join (th[cnt], NULL) != 0)
+ {
+ printf ("join of thread %d failed\n", cnt);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-once3.c b/test/nptl/tst-once3.c
new file mode 100644
index 000000000..43b354a39
--- /dev/null
+++ b/test/nptl/tst-once3.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002, 2003 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 <time.h>
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("once_handler1: mutex_lock failed");
+ exit (1);
+ }
+ puts ("once_handler1: locked");
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler1: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cond_wait (&cond, &mut);
+
+ /* We should never get here. */
+ exit (42);
+}
+
+static void
+once_handler2 (void)
+{
+ global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+ cl_called = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_cleanup_push (cl, NULL)
+
+ pthread_once (&once, once_handler1);
+
+ pthread_cleanup_pop (0);
+
+ /* We should never get here. */
+ puts ("pthread_once in tf returned");
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("first create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+ /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+ call incorrectly resumes and tries to get the mutex. */
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ /* Cancel the thread. */
+ puts ("going to cancel");
+ if (pthread_cancel (th) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *result;
+ pthread_join (th, &result);
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+
+ if (cl_called != 1)
+ {
+ puts ("cleanup handler not called");
+ return 1;
+ }
+
+ pthread_once (&once, once_handler2);
+
+ if (global != 1)
+ {
+ puts ("global still 0");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-once4.c b/test/nptl/tst-once4.c
new file mode 100644
index 000000000..35bae3c0e
--- /dev/null
+++ b/test/nptl/tst-once4.c
@@ -0,0 +1,202 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("once_handler1: mutex_lock failed");
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler1: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cond_wait (&cond, &mut);
+
+ /* We should never get here. */
+}
+
+
+static void
+once_handler2 (void)
+{
+ global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+ ++cl_called;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+ pthread_cleanup_push (cl, NULL);
+
+ pthread_once (&once, once_handler1);
+
+ pthread_cleanup_pop (0);
+
+ /* We should never get here. */
+ puts ("pthread_once in tf returned");
+ exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+ pthread_cleanup_push (cl, NULL);
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("once_handler2: barrier_wait failed");
+ exit (1);
+ }
+
+ pthread_cleanup_pop (0);
+
+ pthread_once (&once, once_handler2);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th[2];
+
+ if (pthread_barrier_init (&bar, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[0], NULL, tf1, NULL) != 0)
+ {
+ puts ("first create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("first barrier_wait failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&mut) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+ /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+ call incorrectly resumes and tries to get the mutex. */
+ if (pthread_mutex_unlock (&mut) != 0)
+ {
+ puts ("mutex_unlock failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[1], NULL, tf2, NULL) != 0)
+ {
+ puts ("second create failed");
+ return 1;
+ }
+
+ r = pthread_barrier_wait (&bar);
+ if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("second barrier_wait failed");
+ return 1;
+ }
+
+ /* Give the second thread a chance to reach the pthread_once call. */
+ sleep (2);
+
+ /* Cancel the thread. */
+ if (pthread_cancel (th[0]) != 0)
+ {
+ puts ("cancel failed");
+ return 1;
+ }
+
+ void *result;
+ pthread_join (th[0], &result);
+ if (result != PTHREAD_CANCELED)
+ {
+ puts ("first join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+
+ puts ("joined first thread");
+
+ pthread_join (th[1], &result);
+ if (result != NULL)
+ {
+ puts ("second join didn't return PTHREAD_CANCELED");
+ return 1;
+ }
+
+ if (global != 1)
+ {
+ puts ("global still 0");
+ return 1;
+ }
+
+ if (cl_called != 1)
+ {
+ printf ("cl_called = %d\n", cl_called);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-popen1.c b/test/nptl/tst-popen1.c
new file mode 100644
index 000000000..a9d077371
--- /dev/null
+++ b/test/nptl/tst-popen1.c
@@ -0,0 +1,60 @@
+/* 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 <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void *
+dummy (void *x)
+{
+ return NULL;
+}
+
+static char buf[sizeof "something\n"];
+
+static int
+do_test (void)
+{
+ FILE *f;
+ pthread_t p;
+ int err;
+
+ f = popen ("echo something", "r");
+ if (f == NULL)
+ error (EXIT_FAILURE, errno, "popen failed");
+ if (fgets (buf, sizeof (buf), f) == NULL)
+ error (EXIT_FAILURE, 0, "fgets failed");
+ if (strcmp (buf, "something\n"))
+ error (EXIT_FAILURE, 0, "read wrong data");
+ if (pclose (f))
+ error (EXIT_FAILURE, errno, "pclose returned non-zero");
+ if ((err = pthread_create (&p, NULL, dummy, NULL)))
+ error (EXIT_FAILURE, err, "pthread_create failed");
+ if ((err = pthread_join (p, NULL)))
+ error (EXIT_FAILURE, err, "pthread_join failed");
+ exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock1.c b/test/nptl/tst-rwlock1.c
new file mode 100644
index 000000000..c97e0e60f
--- /dev/null
+++ b/test/nptl/tst-rwlock1.c
@@ -0,0 +1,117 @@
+/* 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>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("1st rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("2nd rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("1st rwlock_unlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_unlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("2nd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("1st rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_wrlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("3rd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("2nd rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_wrlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("4th rwlock_unlock failed");
+ return 1;
+ }
+ puts ("4th rwlock_unlock succeeded");
+
+ if (pthread_rwlock_rdlock (&r) != 0)
+ {
+ puts ("3rd rwlock_rdlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_rdlock succeeded");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("5th rwlock_unlock failed");
+ return 1;
+ }
+ puts ("5th rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock10.c b/test/nptl/tst-rwlock10.c
new file mode 100644
index 000000000..43156eae6
--- /dev/null
+++ b/test/nptl/tst-rwlock10.c
@@ -0,0 +1,21 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ 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; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock8.c"
diff --git a/test/nptl/tst-rwlock11.c b/test/nptl/tst-rwlock11.c
new file mode 100644
index 000000000..ed9af7edc
--- /dev/null
+++ b/test/nptl/tst-rwlock11.c
@@ -0,0 +1,21 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ 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; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock9.c"
diff --git a/test/nptl/tst-rwlock12.c b/test/nptl/tst-rwlock12.c
new file mode 100644
index 000000000..91f25d3b1
--- /dev/null
+++ b/test/nptl/tst-rwlock12.c
@@ -0,0 +1,208 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-rwlock12.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_mutex_t *m;
+ pthread_mutexattr_t ma;
+ pthread_rwlock_t *r;
+ pthread_rwlockattr_t ra;
+ pid_t pid;
+ int status = 0;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+ & ~(__alignof (pthread_rwlock_t) - 1));
+ /* The following assumes alignment for a mutex is at least as high
+ as that for a rwlock. Which is true in our case. */
+ m = (pthread_mutex_t *) (r + 1);
+
+ if (pthread_rwlockattr_init (&ra) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_setpshared (&ra, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("rwlockattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_init (r, &ra) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_init (&ma) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("mutexattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_mutex_init (m, &ma) != 0)
+ {
+ puts ("mutex_init failed");
+ return 1;
+ }
+
+ /* Lock the mutex. */
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Lock the mutex. */
+ if (pthread_mutex_lock (m) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return 1;
+ }
+
+ /* Try to get the rwlock. */
+ if (pthread_rwlock_trywrlock (r) == 0)
+ {
+ puts ("rwlock_trywrlock succeeded");
+ return 1;
+ }
+
+ /* Try again. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
+ int e = pthread_rwlock_timedwrlock (r, &ts);
+ if (e == 0)
+ {
+ puts ("rwlock_timedwrlock succeeded");
+ return 1;
+ }
+ if (e != ETIMEDOUT)
+ {
+ puts ("rwlock_timedwrlock didn't return ETIMEDOUT");
+ status = 1;
+ }
+
+ if (pthread_rwlock_tryrdlock (r) == 0)
+ {
+ puts ("rwlock_tryrdlock succeeded");
+ return 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (r, &ts);
+ if (e == 0)
+ {
+ puts ("rwlock_timedrdlock succeeded");
+ return 1;
+ }
+ if (e != ETIMEDOUT)
+ {
+ puts ("rwlock_timedrdlock didn't return ETIMEDOUT");
+ status = 1;
+ }
+ }
+ else
+ {
+ /* Lock the rwlock for writing. */
+ if (pthread_rwlock_wrlock (r) != 0)
+ {
+ puts ("rwlock_wrlock failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+
+ /* Allow the child to run. */
+ if (pthread_mutex_unlock (m) != 0)
+ {
+ puts ("mutex_unlock failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+
+ /* Just wait for the child. */
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("waitpid failed");
+ kill (pid, SIGTERM);
+ return 1;
+ }
+ }
+
+ return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock13.c b/test/nptl/tst-rwlock13.c
new file mode 100644
index 000000000..61d5b83e1
--- /dev/null
+++ b/test/nptl/tst-rwlock13.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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 <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ int ret;
+
+ memset (&r, 0xaa, sizeof (r));
+ if ((ret = pthread_rwlock_init (&r, NULL)) != 0)
+ {
+ printf ("rwlock_init failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_rdlock (&r)) != 0)
+ {
+ printf ("rwlock_rdlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_unlock (&r)) != 0)
+ {
+ printf ("rwlock_unlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_wrlock (&r)) != 0)
+ {
+ printf ("rwlock_wrlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_unlock (&r)) != 0)
+ {
+ printf ("second rwlock_unlock failed: %d\n", ret);
+ return 1;
+ }
+
+ if ((ret = pthread_rwlock_destroy (&r)) != 0)
+ {
+ printf ("second rwlock_destroy failed: %d\n", ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock14.c b/test/nptl/tst-rwlock14.c
new file mode 100644
index 000000000..fc0d3d219
--- /dev/null
+++ b/test/nptl/tst-rwlock14.c
@@ -0,0 +1,169 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+
+static pthread_barrier_t b;
+static pthread_rwlock_t r = PTHREAD_RWLOCK_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ /* Lock the read-write lock. */
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("tf: cannot lock rwlock");
+ exit (EXIT_FAILURE);
+ }
+
+ pthread_t mt = *(pthread_t *) arg;
+
+ pthread_barrier_wait (&b);
+
+ /* This call will never return. */
+ pthread_join (mt, NULL);
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ struct timespec ts;
+
+ if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+ {
+ puts ("clock_gettime failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ pthread_t me = pthread_self ();
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &me) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ /* Wait until the rwlock is locked. */
+ pthread_barrier_wait (&b);
+
+ ts.tv_nsec = -1;
+
+ int e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("first rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("first rwlock_timedwrlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("first rwlock_timedwrlock did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = 1000000000;
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("second rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("second rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("second rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ ts.tv_nsec = 0x100001000LL;
+ if (ts.tv_nsec != 0x100001000LL)
+ ts.tv_nsec = 2000000000;
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("third rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("third rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("third rwlock_timedrdlock did not fail");
+ result = 1;
+ }
+ else if (e != EINVAL)
+ {
+ puts ("third rwlock_timedrdlock did not return EINVAL");
+ result = 1;
+ }
+
+ if (result == 0)
+ puts ("no bugs");
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock2.c b/test/nptl/tst-rwlock2.c
new file mode 100644
index 000000000..6f38682b8
--- /dev/null
+++ b/test/nptl/tst-rwlock2.c
@@ -0,0 +1,143 @@
+/* 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 <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ int e;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("1st rwlock_wrlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_wrlock succeeded");
+
+ e = pthread_rwlock_tryrdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+ e = pthread_rwlock_trywrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_trywrlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_trywrlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on rwlock with writer failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("1st rwlock_unlock failed");
+ return 1;
+ }
+ puts ("1st rwlock_unlock succeeded");
+
+ if (pthread_rwlock_tryrdlock (&r) != 0)
+ {
+ puts ("rwlock_tryrdlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_trywrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_trywrlock on rwlock with reader succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_trywrlock on rwlock with reader return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on rwlock with reader failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("2nd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("2nd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_trywrlock (&r) != 0)
+ {
+ puts ("rwlock_trywrlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_tryrdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EBUSY)
+ {
+ puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+ return 1;
+ }
+ puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("3rd rwlock_unlock failed");
+ return 1;
+ }
+ puts ("3rd rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock3.c b/test/nptl/tst-rwlock3.c
new file mode 100644
index 000000000..c1cac876d
--- /dev/null
+++ b/test/nptl/tst-rwlock3.c
@@ -0,0 +1,93 @@
+/* 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. */
+
+/* This test case checks more than standard compliance. An
+ implementation may provide this service but it is not required to
+ do so. */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+
+
+static int
+do_test (void)
+{
+ pthread_rwlock_t r;
+ int e;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+ puts ("rwlock_init succeeded");
+
+ if (pthread_rwlock_trywrlock (&r) != 0)
+ {
+ puts ("rwlock_trywrlock on unlocked rwlock failed");
+ return 1;
+ }
+ puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+ e = pthread_rwlock_rdlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_rdlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EDEADLK)
+ {
+ puts ("rwlock_rdlock on rwlock with writer failed != EDEADLK");
+ return 1;
+ }
+ puts ("rwlock_rdlock on rwlock with writer failed with EDEADLK");
+
+ e = pthread_rwlock_wrlock (&r);
+ if (e == 0)
+ {
+ puts ("rwlock_wrlock on rwlock with writer succeeded");
+ return 1;
+ }
+ if (e != EDEADLK)
+ {
+ puts ("rwlock_wrlock on rwlock with writer failed != EDEADLK");
+ return 1;
+ }
+ puts ("rwlock_wrlock on rwlock with writer failed with EDEADLK");
+
+ if (pthread_rwlock_unlock (&r) != 0)
+ {
+ puts ("rwlock_unlock failed");
+ return 1;
+ }
+ puts ("rwlock_unlock succeeded");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ puts ("rwlock_destroy failed");
+ return 1;
+ }
+ puts ("rwlock_destroy succeeded");
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock4.c b/test/nptl/tst-rwlock4.c
new file mode 100644
index 000000000..8de0121b3
--- /dev/null
+++ b/test/nptl/tst-rwlock4.c
@@ -0,0 +1,190 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-rwlock4.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_rwlock_t *r;
+ pthread_rwlockattr_t a;
+ pid_t pid;
+ char *p;
+ int err;
+ int s;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+ & ~(__alignof (pthread_rwlock_t) - 1));
+ p = (char *) (r + 1);
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ puts ("rwlockattr_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+ {
+ puts ("1st rwlockattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_PRIVATE)
+ {
+ puts ("default pshared value wrong");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("rwlockattr_setpshared failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+ {
+ puts ("2nd rwlockattr_getpshared failed");
+ return 1;
+ }
+
+ if (s != PTHREAD_PROCESS_SHARED)
+ {
+ puts ("pshared value after setpshared call wrong");
+ return 1;
+ }
+
+ if (pthread_rwlock_init (r, &a) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_rdlock (r) != 0)
+ {
+ puts ("rwlock_rdlock failed");
+ return 1;
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ puts ("rwlockattr_destroy failed");
+ return 1;
+ }
+
+ err = pthread_rwlock_trywrlock (r);
+ if (err == 0)
+ {
+ puts ("rwlock_trywrlock succeeded");
+ return 1;
+ }
+ else if (err != EBUSY)
+ {
+ puts ("rwlock_trywrlock didn't return EBUSY");
+ return 1;
+ }
+
+ *p = 0;
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Play some lock ping-pong. It's our turn to unlock first. */
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ return 1;
+ }
+
+ if (pthread_rwlock_unlock (r) != 0)
+ {
+ puts ("child: 1st rwlock_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ if (pthread_rwlock_wrlock (r) != 0)
+ {
+ puts ("parent: rwlock_wrlock failed");
+ return 1;
+ }
+
+ if (*p != 1)
+ {
+ puts ("*p != 1");
+ return 1;
+ }
+
+ puts ("parent done");
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock5.c b/test/nptl/tst-rwlock5.c
new file mode 100644
index 000000000..a04eb2670
--- /dev/null
+++ b/test/nptl/tst-rwlock5.c
@@ -0,0 +1,87 @@
+/* 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 <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t r;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_rwlock_wrlock (&r) == 0)
+ {
+ puts ("child: rwlock_wrlock succeeded");
+ exit (1);
+ }
+
+ puts ("child: rwlock_wrlock returned");
+
+ exit (1);
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_rwlock_init (&r, NULL) != 0)
+ {
+ puts ("rwlock_init failed");
+ return 1;
+ }
+
+ if (pthread_rwlock_wrlock (&r) != 0)
+ {
+ puts ("rwlock_wrlock failed");
+ return 1;
+ }
+
+ if (pthread_mutex_lock (&m) != 0)
+ {
+ puts ("mutex_lock failed");
+ return 1;
+ }
+
+ /* Set an alarm for 1 second. The wrapper will expect this. */
+ alarm (1);
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ /* This call should never return. */
+ pthread_mutex_lock (&m);
+
+ puts ("2nd mutex_lock returned");
+ return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock6.c b/test/nptl/tst-rwlock6.c
new file mode 100644
index 000000000..3b525b9d5
--- /dev/null
+++ b/test/nptl/tst-rwlock6.c
@@ -0,0 +1,226 @@
+/* Copyright (C) 2002, 2003 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 <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+
+static int kind[] =
+ {
+ PTHREAD_RWLOCK_PREFER_READER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NP,
+ };
+
+
+static void *
+tf (void *arg)
+{
+ pthread_rwlock_t *r = arg;
+
+ /* Timeout: 0.3 secs. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 300000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ puts ("child calling timedrdlock");
+
+ int err = pthread_rwlock_timedrdlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("rwlock_timedrdlock returned");
+ pthread_exit ((void *) 1l);
+ }
+
+ if (err != ETIMEDOUT)
+ {
+ printf ("err = %s (%d), expected %s (%d)\n",
+ strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+ pthread_exit ((void *) 1l);
+ }
+
+ puts ("1st child timedrdlock done");
+
+ struct timeval tv2;
+ (void) gettimeofday (&tv2, NULL);
+
+ timersub (&tv2, &tv, &tv);
+
+ if (tv.tv_usec < 200000)
+ {
+ puts ("timeout too short");
+ pthread_exit ((void *) 1l);
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10;
+ /* Note that the following operation makes ts invalid. */
+ ts.tv_nsec += 1000000000;
+
+ err = pthread_rwlock_timedrdlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("2nd timedrdlock succeeded");
+ pthread_exit ((void *) 1l);
+ }
+ if (err != EINVAL)
+ {
+ puts ("2nd timedrdlock did not return EINVAL");
+ pthread_exit ((void *) 1l);
+ }
+
+ puts ("2nd child timedrdlock done");
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ size_t cnt;
+ for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+ {
+ pthread_rwlock_t r;
+ pthread_rwlockattr_t a;
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_t failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+ {
+ printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_init (&r, &a) != 0)
+ {
+ printf ("round %Zu: rwlock_init failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ++ts.tv_sec;
+
+ /* Get a write lock. */
+ int e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e != 0)
+ {
+ printf ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
+ exit (1);
+ }
+
+ puts ("1st timedwrlock done");
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ++ts.tv_sec;
+ e = pthread_rwlock_timedrdlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("timedrdlock succeeded");
+ exit (1);
+ }
+ if (e != EDEADLK)
+ {
+ puts ("timedrdlock did not return EDEADLK");
+ exit (1);
+ }
+
+ puts ("1st timedrdlock done");
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ++ts.tv_sec;
+ e = pthread_rwlock_timedwrlock (&r, &ts);
+ if (e == 0)
+ {
+ puts ("2nd timedwrlock succeeded");
+ exit (1);
+ }
+ if (e != EDEADLK)
+ {
+ puts ("2nd timedwrlock did not return EDEADLK");
+ exit (1);
+ }
+
+ puts ("2nd timedwrlock done");
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &r) != 0)
+ {
+ printf ("round %Zu: create failed\n", cnt);
+ exit (1);
+ }
+
+ puts ("started thread");
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("round %Zu: join failed\n", cnt);
+ exit (1);
+ }
+ if (status != NULL)
+ {
+ printf ("failure in round %Zu\n", cnt);
+ exit (1);
+ }
+
+ puts ("joined thread");
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ printf ("round %Zu: rwlock_destroy failed\n", cnt);
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock7.c b/test/nptl/tst-rwlock7.c
new file mode 100644
index 000000000..1f34c0650
--- /dev/null
+++ b/test/nptl/tst-rwlock7.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002, 2003 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 <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+
+static int kind[] =
+ {
+ PTHREAD_RWLOCK_PREFER_READER_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+ PTHREAD_RWLOCK_PREFER_WRITER_NP,
+ };
+
+
+static void *
+tf (void *arg)
+{
+ pthread_rwlock_t *r = arg;
+
+ /* Timeout: 0.3 secs. */
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 300000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ int err = pthread_rwlock_timedwrlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("rwlock_timedwrlock returned");
+ pthread_exit ((void *) 1l);
+ }
+
+ if (err != ETIMEDOUT)
+ {
+ printf ("err = %s (%d), expected %s (%d)\n",
+ strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+ pthread_exit ((void *) 1l);
+ }
+
+ struct timeval tv2;
+ (void) gettimeofday (&tv2, NULL);
+
+ timersub (&tv2, &tv, &tv);
+
+ if (tv.tv_usec < 200000)
+ {
+ puts ("timeout too short");
+ pthread_exit ((void *) 1l);
+ }
+
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_sec += 10;
+ /* Note that the following operation makes ts invalid. */
+ ts.tv_nsec += 1000000000;
+
+ err = pthread_rwlock_timedwrlock (r, &ts);
+ if (err == 0)
+ {
+ puts ("2nd timedwrlock succeeded");
+ pthread_exit ((void *) 1l);
+ }
+ if (err != EINVAL)
+ {
+ puts ("2nd timedwrlock did not return EINVAL");
+ pthread_exit ((void *) 1l);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ size_t cnt;
+ for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+ {
+ pthread_rwlock_t r;
+ pthread_rwlockattr_t a;
+
+ if (pthread_rwlockattr_init (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_t failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+ {
+ printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_init (&r, &a) != 0)
+ {
+ printf ("round %Zu: rwlock_init failed\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlockattr_destroy (&a) != 0)
+ {
+ printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+ exit (1);
+ }
+
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+
+ struct timespec ts;
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ++ts.tv_sec;
+
+ /* Get a read lock. */
+ if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
+ {
+ printf ("round %Zu: rwlock_timedrdlock failed\n", cnt);
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, &r) != 0)
+ {
+ printf ("round %Zu: create failed\n", cnt);
+ exit (1);
+ }
+
+ void *status;
+ if (pthread_join (th, &status) != 0)
+ {
+ printf ("round %Zu: join failed\n", cnt);
+ exit (1);
+ }
+ if (status != NULL)
+ {
+ printf ("failure in round %Zu\n", cnt);
+ exit (1);
+ }
+
+ if (pthread_rwlock_destroy (&r) != 0)
+ {
+ printf ("round %Zu: rwlock_destroy failed\n", cnt);
+ exit (1);
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock8.c b/test/nptl/tst-rwlock8.c
new file mode 100644
index 000000000..7eeaea885
--- /dev/null
+++ b/test/nptl/tst-rwlock8.c
@@ -0,0 +1,164 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2000, 2003 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 <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define DELAY 1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < WRITETRIES; ++n)
+ {
+ printf ("writer thread %ld tries again\n", (long int) nr);
+
+ if (pthread_rwlock_wrlock (&lock) != 0)
+ {
+ puts ("wrlock failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for writer failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < READTRIES; ++n)
+ {
+ printf ("reader thread %ld tries again\n", (long int) nr);
+
+ if (pthread_rwlock_rdlock (&lock) != 0)
+ {
+ puts ("rdlock failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for reader failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t thwr[NWRITERS];
+ pthread_t thrd[NREADERS];
+ int n;
+ void *res;
+
+ /* Make standard error the same as standard output. */
+ dup2 (1, 2);
+
+ /* Make sure we see all message, even those on stdout. */
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_create (&thwr[n], NULL, writer_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("writer create failed");
+ exit (1);
+ }
+
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_create (&thrd[n], NULL, reader_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("reader create failed");
+ exit (1);
+ }
+
+ /* Wait for all the threads. */
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_join (thwr[n], &res) != 0)
+ {
+ puts ("writer join failed");
+ exit (1);
+ }
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_join (thrd[n], &res) != 0)
+ {
+ puts ("reader join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-rwlock9.c b/test/nptl/tst-rwlock9.c
new file mode 100644
index 000000000..a5522ce48
--- /dev/null
+++ b/test/nptl/tst-rwlock9.c
@@ -0,0 +1,203 @@
+/* Test program for timedout read/write lock functions.
+ Copyright (C) 2000, 2003 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 <errno.h>
+#include <error.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define TIMEOUT 1000000
+#define DELAY 1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < WRITETRIES; ++n)
+ {
+ int e;
+ do
+ {
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_nsec += 2 * TIMEOUT;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ printf ("writer thread %ld tries again\n", (long int) nr);
+
+ e = pthread_rwlock_timedwrlock (&lock, &ts);
+ if (e != 0 && e != ETIMEDOUT)
+ {
+ puts ("timedwrlock failed");
+ exit (1);
+ }
+ }
+ while (e == ETIMEDOUT);
+
+ printf ("writer thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for writer failed");
+ exit (1);
+ }
+
+ printf ("writer thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+ struct timespec ts;
+ struct timespec delay;
+ int n;
+
+ delay.tv_sec = 0;
+ delay.tv_nsec = DELAY;
+
+ for (n = 0; n < READTRIES; ++n)
+ {
+ int e;
+ do
+ {
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+ ts.tv_nsec += TIMEOUT;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ printf ("reader thread %ld tries again\n", (long int) nr);
+
+ e = pthread_rwlock_timedrdlock (&lock, &ts);
+ if (e != 0 && e != ETIMEDOUT)
+ {
+ puts ("timedrdlock failed");
+ exit (1);
+ }
+ }
+ while (e == ETIMEDOUT);
+
+ printf ("reader thread %ld succeeded\n", (long int) nr);
+
+ nanosleep (&delay, NULL);
+
+ if (pthread_rwlock_unlock (&lock) != 0)
+ {
+ puts ("unlock for reader failed");
+ exit (1);
+ }
+
+ printf ("reader thread %ld released\n", (long int) nr);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t thwr[NWRITERS];
+ pthread_t thrd[NREADERS];
+ int n;
+ void *res;
+
+ /* Make standard error the same as standard output. */
+ dup2 (1, 2);
+
+ /* Make sure we see all message, even those on stdout. */
+ setvbuf (stdout, NULL, _IONBF, 0);
+
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_create (&thwr[n], NULL, writer_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("writer create failed");
+ exit (1);
+ }
+
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_create (&thrd[n], NULL, reader_thread,
+ (void *) (long int) n) != 0)
+ {
+ puts ("reader create failed");
+ exit (1);
+ }
+
+ /* Wait for all the threads. */
+ for (n = 0; n < NWRITERS; ++n)
+ if (pthread_join (thwr[n], &res) != 0)
+ {
+ puts ("writer join failed");
+ exit (1);
+ }
+ for (n = 0; n < NREADERS; ++n)
+ if (pthread_join (thrd[n], &res) != 0)
+ {
+ puts ("reader join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#undef TIMEOUT
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-sched1.c b/test/nptl/tst-sched1.c
new file mode 100644
index 000000000..4d0702c79
--- /dev/null
+++ b/test/nptl/tst-sched1.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003 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>
+#include <sys/types.h>
+
+
+static int global;
+
+static void *
+tf (void *a)
+{
+ global = 1;
+
+ return 0;
+}
+
+
+int
+do_test (void)
+{
+ pthread_t th;
+ pthread_attr_t at;
+
+ if (pthread_attr_init (&at) != 0)
+ {
+ puts ("attr_init failed");
+ return 1;
+ }
+
+ if (pthread_attr_setschedpolicy (&at, SCHED_OTHER) != 0)
+ {
+ puts ("attr_setschedpolicy failed");
+ return 1;
+ }
+
+ struct sched_param pa;
+ if (sched_getparam (getpid (), &pa) != 0)
+ {
+ puts ("sched_getschedparam failed");
+ return 1;
+ }
+
+ if (pthread_attr_setschedparam (&at, &pa) != 0)
+ {
+ puts ("attr_setschedparam failed");
+ return 1;
+ }
+
+ if (pthread_attr_setinheritsched (&at, PTHREAD_EXPLICIT_SCHED) != 0)
+ {
+ puts ("attr_setinheritsched failed");
+ return 1;
+ }
+
+ if (pthread_create (&th, &at, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ int e = pthread_join (th, NULL);
+ if (e != 0)
+ {
+ printf ("join failed: %d\n", e);
+ return 1;
+ }
+
+ if (global == 0)
+ {
+ puts ("thread didn't run");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-spin1.c b/test/nptl/tst-spin1.c
new file mode 100644
index 000000000..259b4b4d6
--- /dev/null
+++ b/test/nptl/tst-spin1.c
@@ -0,0 +1,57 @@
+/* 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>
+
+
+static int
+do_test (void)
+{
+ pthread_spinlock_t s;
+
+ if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (&s) != 0)
+ {
+ puts ("spin_lock failed");
+ return 1;
+ }
+
+ if (pthread_spin_unlock (&s) != 0)
+ {
+ puts ("spin_unlock failed");
+ return 1;
+ }
+
+ if (pthread_spin_destroy (&s) != 0)
+ {
+ puts ("spin_destroy failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-spin2.c b/test/nptl/tst-spin2.c
new file mode 100644
index 000000000..5b1df6c4a
--- /dev/null
+++ b/test/nptl/tst-spin2.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 2002, 2003, 2004 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 <errno.h>
+#include <pthread.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static int
+do_test (void)
+{
+ size_t ps = sysconf (_SC_PAGESIZE);
+ char tmpfname[] = "/tmp/tst-spin2.XXXXXX";
+ char data[ps];
+ void *mem;
+ int fd;
+ pthread_spinlock_t *s;
+ pid_t pid;
+ char *p;
+ int err;
+
+ fd = mkstemp (tmpfname);
+ if (fd == -1)
+ {
+ printf ("cannot open temporary file: %m\n");
+ return 1;
+ }
+
+ /* Make sure it is always removed. */
+ unlink (tmpfname);
+
+ /* Create one page of data. */
+ memset (data, '\0', ps);
+
+ /* Write the data to the file. */
+ if (write (fd, data, ps) != (ssize_t) ps)
+ {
+ puts ("short write");
+ return 1;
+ }
+
+ mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mem == MAP_FAILED)
+ {
+ printf ("mmap failed: %m\n");
+ return 1;
+ }
+
+ s = (pthread_spinlock_t *) (((uintptr_t) mem
+ + __alignof (pthread_spinlock_t))
+ & ~(__alignof (pthread_spinlock_t) - 1));
+ p = (char *) (s + 1);
+
+ if (pthread_spin_init (s, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (s) != 0)
+ {
+ puts ("spin_lock failed");
+ return 1;
+ }
+
+ err = pthread_spin_trylock (s);
+ if (err == 0)
+ {
+ puts ("1st spin_trylock succeeded");
+ return 1;
+ }
+ else if (err != EBUSY)
+ {
+ puts ("1st spin_trylock didn't return EBUSY");
+ return 1;
+ }
+
+ err = pthread_spin_unlock (s);
+ if (err != 0)
+ {
+ puts ("parent: spin_unlock failed");
+ return 1;
+ }
+
+ err = pthread_spin_trylock (s);
+ if (err != 0)
+ {
+ puts ("2nd spin_trylock failed");
+ return 1;
+ }
+
+ *p = 0;
+
+ puts ("going to fork now");
+ pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ return 1;
+ }
+ else if (pid == 0)
+ {
+ /* Play some lock ping-pong. It's our turn to unlock first. */
+ if ((*p)++ != 0)
+ {
+ puts ("child: *p != 0");
+ return 1;
+ }
+
+ if (pthread_spin_unlock (s) != 0)
+ {
+ puts ("child: 1st spin_unlock failed");
+ return 1;
+ }
+
+ puts ("child done");
+ }
+ else
+ {
+ if (pthread_spin_lock (s) != 0)
+ {
+ puts ("parent: 2nd spin_lock failed");
+ return 1;
+ }
+
+ puts ("waiting for child");
+
+ waitpid (pid, NULL, 0);
+
+ puts ("parent done");
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-spin3.c b/test/nptl/tst-spin3.c
new file mode 100644
index 000000000..443774032
--- /dev/null
+++ b/test/nptl/tst-spin3.c
@@ -0,0 +1,55 @@
+/* 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
+do_test (void)
+{
+ pthread_spinlock_t s;
+
+ if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+ {
+ puts ("spin_init failed");
+ return 1;
+ }
+
+ if (pthread_spin_lock (&s) != 0)
+ {
+ puts ("1st spin_lock failed");
+ return 1;
+ }
+
+ /* Set an alarm for 1 second. The wrapper will expect this. */
+ alarm (1);
+
+ /* This call should never return. */
+ pthread_spin_lock (&s);
+
+ puts ("2nd spin_lock returned");
+ return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tsd1.c b/test/nptl/tst-tsd1.c
new file mode 100644
index 000000000..51b2d0cb2
--- /dev/null
+++ b/test/nptl/tst-tsd1.c
@@ -0,0 +1,118 @@
+/* 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 <string.h>
+
+
+static int
+do_test (void)
+{
+ pthread_key_t key1;
+ pthread_key_t key2;
+ void *value;
+ int result = 0;
+ int err;
+
+ err = pthread_key_create (&key1, NULL);
+ if (err != 0)
+ {
+ printf ("1st key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Initial value must be NULL. */
+ value = pthread_getspecific (key1);
+ if (value != NULL)
+ {
+ puts ("1st getspecific != NULL");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -2l);
+ if (err != 0)
+ {
+ printf ("1st setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("2nd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -2l)
+ {
+ puts ("2nd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_setspecific (key1, (void *) -3l);
+ if (err != 0)
+ {
+ printf ("2nd setspecific failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ value = pthread_getspecific (key1);
+ if (value == NULL)
+ {
+ puts ("3rd getspecific == NULL\n");
+ result = 1;
+ }
+ else if (value != (void *) -3l)
+ {
+ puts ("3rd getspecific != -2l\n");
+ result = 1;
+ }
+
+ err = pthread_key_delete (key1);
+ if (err != 0)
+ {
+ printf ("key_delete failed: %s\n", strerror (err));
+ result = 1;
+ }
+
+
+ err = pthread_key_create (&key2, NULL);
+ if (err != 0)
+ {
+ printf ("2nd key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (key1 != key2)
+ puts ("key1 != key2; no more tests performed");
+ else
+ {
+ value = pthread_getspecific (key2);
+ if (value != NULL)
+ {
+ puts ("4th getspecific != NULL");
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tsd2.c b/test/nptl/tst-tsd2.c
new file mode 100644
index 000000000..19d8a69f9
--- /dev/null
+++ b/test/nptl/tst-tsd2.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2002, 2003 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 <string.h>
+
+
+static int result;
+
+
+static void
+destr (void *arg)
+{
+ if (arg != (void *) -2l)
+ result = 2;
+ else
+ result = 0;
+}
+
+
+static void *
+tf (void *arg)
+{
+ pthread_key_t key = (pthread_key_t) (long int) arg;
+ int err;
+
+ err = pthread_setspecific (key, (void *) -2l);
+ if (err != 0)
+ result = 3;
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_key_t key;
+ pthread_t th;
+ int err;
+
+ err = pthread_key_create (&key, destr);
+ if (err != 0)
+ {
+ printf ("key_create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ result = 1;
+
+ err = pthread_create (&th, NULL, tf, (void *) (long int) key);
+ if (err != 0)
+ {
+ printf ("create failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ /* Wait for the thread to terminate. */
+ err = pthread_join (th, NULL);
+ if (err != 0)
+ {
+ printf ("join failed: %s\n", strerror (err));
+ return 1;
+ }
+
+ if (result == 1)
+ puts ("destructor not called");
+ else if (result == 2)
+ puts ("destructor got passed a wrong value");
+ else if (result == 3)
+ puts ("setspecific in child failed");
+ else if (result != 0)
+ puts ("result != 0");
+
+ return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tsd3.c b/test/nptl/tst-tsd3.c
new file mode 100644
index 000000000..6cdf74991
--- /dev/null
+++ b/test/nptl/tst-tsd3.c
@@ -0,0 +1,129 @@
+/* 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 <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_key_t key1;
+static pthread_key_t key2;
+
+
+static int left;
+
+
+static void
+destr1 (void *arg)
+{
+ if (--left > 0)
+ {
+ puts ("set key2");
+
+ if (pthread_setspecific (key2, (void *) 1l) != 0)
+ {
+ puts ("destr1: setspecific failed");
+ exit (1);
+ }
+ }
+}
+
+
+static void
+destr2 (void *arg)
+{
+ if (--left > 0)
+ {
+ puts ("set key1");
+
+ if (pthread_setspecific (key1, (void *) 1l) != 0)
+ {
+ puts ("destr2: setspecific failed");
+ exit (1);
+ }
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ /* Let the destructors work. */
+ left = 7;
+
+ if (pthread_setspecific (key1, (void *) 1l) != 0
+ || pthread_setspecific (key2, (void *) 1l) != 0)
+ {
+ puts ("tf: setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ /* Allocate two keys, both with destructors. */
+ if (pthread_key_create (&key1, destr1) != 0
+ || pthread_key_create (&key2, destr2) != 0)
+ {
+ puts ("key_create failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (left != 0)
+ {
+ printf ("left == %d\n", left);
+ return 1;
+ }
+
+ if (pthread_getspecific (key1) != NULL)
+ {
+ puts ("key1 data != NULL");
+ return 1;
+ }
+ if (pthread_getspecific (key2) != NULL)
+ {
+ puts ("key2 data != NULL");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tsd4.c b/test/nptl/tst-tsd4.c
new file mode 100644
index 000000000..44bbadb42
--- /dev/null
+++ b/test/nptl/tst-tsd4.c
@@ -0,0 +1,103 @@
+/* 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 <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_key_t key;
+
+
+static int rounds;
+
+
+static void
+destr (void *arg)
+{
+ ++rounds;
+
+ if (pthread_setspecific (key, (void *) 1l) != 0)
+ {
+ puts ("destr: setspecific failed");
+ exit (1);
+ }
+}
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_setspecific (key, (void *) 1l) != 0)
+ {
+ puts ("tf: setspecific failed");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+/* This test check non-standard behavior. The standard does not
+ require that the implementation has to stop calling TSD destructors
+ when they are set over and over again. But NPTL does. */
+static int
+do_test (void)
+{
+ /* Allocate two keys, both with destructors. */
+ if (pthread_key_create (&key, destr) != 0)
+ {
+ puts ("key_create failed");
+ return 1;
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ return 1;
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (rounds < PTHREAD_DESTRUCTOR_ITERATIONS)
+ {
+ printf ("rounds == %d, PTHREAD_DESTRUCTOR_ITERATIONS = %d\n",
+ rounds, PTHREAD_DESTRUCTOR_ITERATIONS);
+ return 1;
+ }
+
+ if (pthread_getspecific (key) != NULL)
+ {
+ puts ("key data != NULL");
+ return 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"