summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author"Steven J. Hill" <sjhill@realitydiluted.com>2005-11-16 03:44:44 +0000
committer"Steven J. Hill" <sjhill@realitydiluted.com>2005-11-16 03:44:44 +0000
commit03fcb272ebb449b3ff637903588180c2983d7abc (patch)
treeaf66e8bd389af515690469a22552b06c3edfe4db
parentb823b17fa7dc5a15d822a4f31fe8ee846a65cfae (diff)
downloaduClibc-alpine-03fcb272ebb449b3ff637903588180c2983d7abc.tar.bz2
uClibc-alpine-03fcb272ebb449b3ff637903588180c2983d7abc.tar.xz
Add first set of passing tests for NPTL.
-rw-r--r--test/nptl/tst-basic1.c82
-rw-r--r--test/nptl/tst-basic2.c121
-rw-r--r--test/nptl/tst-basic4.c101
-rw-r--r--test/nptl/tst-basic5.c74
-rw-r--r--test/nptl/tst-basic6.c132
-rw-r--r--test/nptl/tst-join2.c104
-rw-r--r--test/nptl/tst-join3.c123
-rw-r--r--test/nptl/tst-signal1.c189
-rw-r--r--test/nptl/tst-signal2.c198
-rw-r--r--test/nptl/tst-signal4.c60
-rw-r--r--test/nptl/tst-signal5.c111
-rw-r--r--test/nptl/tst-tls1.c122
-rw-r--r--test/nptl/tst-tls2.c216
-rw-r--r--test/nptl/tst-tls3.c216
-rw-r--r--test/nptl/tst-tls3mod.c94
-rw-r--r--test/nptl/tst-tls4.c191
-rw-r--r--test/nptl/tst-tls4moda.c56
-rw-r--r--test/nptl/tst-tls4modb.c65
-rw-r--r--test/nptl/tst-tls5.c120
-rw-r--r--test/nptl/tst-tls5.h28
-rw-r--r--test/nptl/tst-tls5mod.c6
-rw-r--r--test/nptl/tst-tls5moda.c6
-rw-r--r--test/nptl/tst-tls5modb.c6
-rw-r--r--test/nptl/tst-tls5modc.c6
-rw-r--r--test/nptl/tst-tls5modd.c6
-rw-r--r--test/nptl/tst-tls5mode.c8
-rw-r--r--test/nptl/tst-tls5modf.c9
-rwxr-xr-xtest/nptl/tst-tls6.sh45
28 files changed, 2495 insertions, 0 deletions
diff --git a/test/nptl/tst-basic1.c b/test/nptl/tst-basic1.c
new file mode 100644
index 000000000..7637c8e49
--- /dev/null
+++ b/test/nptl/tst-basic1.c
@@ -0,0 +1,82 @@
+/* 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 <unistd.h>
+#include <sys/types.h>
+
+
+static pid_t pid;
+
+static void *
+tf (void *a)
+{
+ if (getpid () != pid)
+ {
+ write (2, "pid mismatch\n", 13);
+ _exit (1);
+ }
+
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ pid = getpid ();
+
+#define N 2
+ pthread_t t[N];
+ int i;
+
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&t[i], NULL, tf, (void *) (long int) (i + 1)) != 0)
+ {
+ write (2, "create failed\n", 14);
+ _exit (1);
+ }
+ else
+ printf ("created thread %d\n", i);
+
+ for (i = 0; i < N; ++i)
+ {
+ void *r;
+ int e;
+ if ((e = pthread_join (t[i], &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+ else if (r != (void *) (long int) (i + 1))
+ {
+ write (2, "result wrong\n", 13);
+ _exit (1);
+ }
+ else
+ printf ("joined thread %d\n", i);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-basic2.c b/test/nptl/tst-basic2.c
new file mode 100644
index 000000000..1c4632ceb
--- /dev/null
+++ b/test/nptl/tst-basic2.c
@@ -0,0 +1,121 @@
+/* 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 <pthread.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define N 20
+
+static pthread_t th[N];
+static pthread_mutex_t lock[N];
+
+
+static void *tf (void *a)
+{
+ uintptr_t idx = (uintptr_t) a;
+
+ pthread_mutex_lock (&lock[idx]);
+
+ return pthread_equal (pthread_self (), th[idx]) ? NULL : (void *) 1l;
+}
+
+
+int
+do_test (void)
+{
+ if (pthread_equal (pthread_self (), pthread_self ()) == 0)
+ {
+ puts ("pthread_equal (pthread_self (), pthread_self ()) 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 i;
+ for (i = 0; i < N; ++i)
+ {
+ if (pthread_mutex_init (&lock[i], NULL) != 0)
+ {
+ puts ("mutex_init failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_lock (&lock[i]) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock[i]) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ printf ("created thread %d\n", i);
+ }
+
+ if (pthread_attr_destroy (&at) != 0)
+ {
+ puts ("attr_destroy failed");
+ return 1;
+ }
+
+ int result = 0;
+ for (i = 0; i < N; ++i)
+ {
+ void *r;
+ int e;
+ if ((e = pthread_join (th[i], &r)) != 0)
+ {
+ printf ("join failed: %d\n", e);
+ _exit (1);
+ }
+ else if (r != NULL)
+ result = 1;
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-basic4.c b/test/nptl/tst-basic4.c
new file mode 100644
index 000000000..6eb6ea9f1
--- /dev/null
+++ b/test/nptl/tst-basic4.c
@@ -0,0 +1,101 @@
+/* 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/wait.h>
+
+
+static void
+final_test (void)
+{
+ puts ("final_test has been called");
+
+#define THE_SIGNAL SIGUSR1
+ kill (getpid (), SIGUSR1);
+}
+
+
+static void *
+tf (void *a)
+{
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ {
+ atexit (final_test);
+
+ pthread_exit (NULL);
+ }
+
+ int r;
+ int e = TEMP_FAILURE_RETRY (waitpid (pid, &r, 0));
+ if (e != pid)
+ {
+ puts ("waitpid failed");
+ exit (1);
+ }
+
+ if (! WIFSIGNALED (r))
+ {
+ puts ("child not signled");
+ exit (1);
+ }
+
+ if (WTERMSIG (r) != THE_SIGNAL)
+ {
+ puts ("child's termination signal wrong");
+ exit (1);
+ }
+
+ 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);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-basic5.c b/test/nptl/tst-basic5.c
new file mode 100644
index 000000000..83a8810f1
--- /dev/null
+++ b/test/nptl/tst-basic5.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 <stdio.h>
+#include <stdlib.h>
+
+
+
+int
+do_test (void)
+{
+ int c = pthread_getconcurrency ();
+ if (c != 0)
+ {
+ puts ("initial concurrencylevel wrong");
+ exit (1);
+ }
+
+ if (pthread_setconcurrency (1) != 0)
+ {
+ puts ("setconcurrency failed");
+ exit (1);
+ }
+
+ c = pthread_getconcurrency ();
+ if (c != 1)
+ {
+ puts ("getconcurrency didn't return the value previous set");
+ exit (1);
+ }
+
+ int e = pthread_setconcurrency (-1);
+ if (e == 0)
+ {
+ puts ("setconcurrency of negative value didn't failed");
+ exit (1);
+ }
+ if (e != EINVAL)
+ {
+ puts ("setconcurrency didn't return EINVAL for negative value");
+ exit (1);
+ }
+
+ c = pthread_getconcurrency ();
+ if (c != 1)
+ {
+ puts ("invalid getconcurrency changed level");
+ exit (1);
+ }
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-basic6.c b/test/nptl/tst-basic6.c
new file mode 100644
index 000000000..413ae034b
--- /dev/null
+++ b/test/nptl/tst-basic6.c
@@ -0,0 +1,132 @@
+/* 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 <string.h>
+#include <unistd.h>
+
+
+static char *p;
+
+static pthread_barrier_t b;
+#define BT \
+ e = pthread_barrier_wait (&b); \
+ if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) \
+ { \
+ puts ("barrier_wait failed"); \
+ exit (1); \
+ }
+
+
+static void *
+tf (void *a)
+{
+ int e;
+
+ BT;
+
+ char *p2 = getcwd (NULL, 0);
+ if (p2 == NULL)
+ {
+ puts ("2nd getcwd failed");
+ exit (1);
+ }
+
+ if (strcmp (p, p2) != 0)
+ {
+ printf ("initial cwd mismatch: \"%s\" vs \"%s\"\n", p, p2);
+ exit (1);
+ }
+
+ free (p);
+ free (p2);
+
+ if (chdir ("..") != 0)
+ {
+ puts ("chdir failed");
+ exit (1);
+ }
+
+ p = getcwd (NULL, 0);
+ if (p == NULL)
+ {
+ puts ("getcwd failed");
+ exit (1);
+ }
+
+ return a;
+}
+
+
+int
+do_test (void)
+{
+ if (pthread_barrier_init (&b, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("create failed");
+ exit (1);
+ }
+
+ p = getcwd (NULL, 0);
+ if (p == NULL)
+ {
+ puts ("getcwd failed");
+ exit (1);
+ }
+
+ int e;
+ BT;
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ char *p2 = getcwd (NULL, 0);
+ if (p2 == NULL)
+ {
+ puts ("2nd getcwd failed");
+ exit (1);
+ }
+
+ if (strcmp (p, p2) != 0)
+ {
+ printf ("cwd after chdir mismatch: \"%s\" vs \"%s\"\n", p, p2);
+ exit (1);
+ }
+
+ free (p);
+ free (p2);
+
+ return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-join2.c b/test/nptl/tst-join2.c
new file mode 100644
index 000000000..2cfab8b0e
--- /dev/null
+++ b/test/nptl/tst-join2.c
@@ -0,0 +1,104 @@
+/* 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>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return NULL;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("mutex_create failed");
+ exit (1);
+ }
+
+ void *status;
+ int val = pthread_tryjoin_np (th, &status);
+ if (val == 0)
+ {
+ puts ("1st tryjoin succeeded");
+ exit (1);
+ }
+ else if (val != EBUSY)
+ {
+ puts ("1st tryjoin didn't return EBUSY");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ while ((val = pthread_tryjoin_np (th, &status)) != 0)
+ {
+ if (val != EBUSY)
+ {
+ printf ("tryjoin returned %s (%d), expected only 0 or EBUSY\n",
+ strerror (val), val);
+ exit (1);
+ }
+
+ /* Delay minimally. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+ }
+
+ if (status != (void *) 42l)
+ {
+ printf ("return value %p, expected %p\n", status, (void *) 42l);
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-join3.c b/test/nptl/tst-join3.c
new file mode 100644
index 000000000..df1135fb5
--- /dev/null
+++ b/test/nptl/tst-join3.c
@@ -0,0 +1,123 @@
+/* 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 <sys/time.h>
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("child: mutex_lock failed");
+ return NULL;
+ }
+
+ return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+ pthread_t th;
+
+ if (pthread_mutex_lock (&lock) != 0)
+ {
+ puts ("mutex_lock failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("mutex_create failed");
+ exit (1);
+ }
+
+ void *status;
+ struct timespec ts;
+ struct timeval tv;
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 200000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ int val = pthread_timedjoin_np (th, &status, &ts);
+ if (val == 0)
+ {
+ puts ("1st timedjoin succeeded");
+ exit (1);
+ }
+ else if (val != ETIMEDOUT)
+ {
+ puts ("1st timedjoin didn't return ETIMEDOUT");
+ exit (1);
+ }
+
+ if (pthread_mutex_unlock (&lock) != 0)
+ {
+ puts ("mutex_unlock failed");
+ exit (1);
+ }
+
+ while (1)
+ {
+ (void) gettimeofday (&tv, NULL);
+ TIMEVAL_TO_TIMESPEC (&tv, &ts);
+ ts.tv_nsec += 200000000;
+ if (ts.tv_nsec >= 1000000000)
+ {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+
+ val = pthread_timedjoin_np (th, &status, &ts);
+ if (val == 0)
+ break;
+
+ if (val != ETIMEDOUT)
+ {
+ printf ("timedjoin returned %s (%d), expected only 0 or ETIMEDOUT\n",
+ strerror (val), val);
+ exit (1);
+ }
+ }
+
+ if (status != (void *) 42l)
+ {
+ printf ("return value %p, expected %p\n", status, (void *) 42l);
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-signal1.c b/test/nptl/tst-signal1.c
new file mode 100644
index 000000000..3022f1846
--- /dev/null
+++ b/test/nptl/tst-signal1.c
@@ -0,0 +1,189 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+ sigdelset (&ss, SIGINT);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("2nd pthread_sigmask failed");
+ exit (1);
+ }
+
+ pthread_barrier_wait (b);
+
+ int sig;
+ int res = sigwait (&ss, &sig);
+ if (res == 0)
+ {
+ printf ("sigwait returned successfully with signal %d\n", sig);
+ exit (1);
+ }
+
+ printf ("sigwait returned with %s (%d)\n", strerror (res), res);
+
+ return NULL;
+}
+
+
+static void
+receiver (void)
+{
+ pthread_t th;
+
+ /* Make sure the process doesn't run forever. */
+ alarm (10);
+
+ sigfillset (&ss);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st pthread_sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, NULL) == 0)
+ {
+ puts ("thread joined?!");
+ exit (1);
+ }
+
+ _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+ int fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ exit (1);
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ receiver ();
+
+ pthread_barrier_wait (b);
+
+ /* Wait a bit more. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+
+ /* Send the signal. */
+ puts ("sending the signal now");
+ kill (pid, SIGINT);
+
+ /* Wait for the process to terminate. */
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("wrong child reported terminated");
+ exit (1);
+ }
+
+ if (!WIFSIGNALED (status))
+ {
+ puts ("child wasn't signalled");
+ exit (1);
+ }
+
+ if (WTERMSIG (status) != SIGINT)
+ {
+ puts ("child not terminated with SIGINT");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-signal2.c b/test/nptl/tst-signal2.c
new file mode 100644
index 000000000..3f2c75d1f
--- /dev/null
+++ b/test/nptl/tst-signal2.c
@@ -0,0 +1,198 @@
+/* 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 <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+#include <string.h>
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+ pthread_barrier_wait (b);
+
+ puts ("child: calling sigwait now");
+
+ int sig;
+ int err;
+ err = sigwait (&ss, &sig);
+ if (err != 0)
+ {
+ printf ("sigwait returned unsuccessfully: %s (%d)\n",
+ strerror (err), err);
+ _exit (1);
+ }
+
+ puts ("sigwait returned");
+
+ if (sig != SIGINT)
+ {
+ printf ("caught signal %d, expected %d (SIGINT)\n", sig, SIGINT);
+ _exit (1);
+ }
+
+ puts ("child thread terminating now");
+
+ return NULL;
+}
+
+
+static void
+receiver (void)
+{
+ pthread_t th;
+
+ /* Make sure the process doesn't run forever. */
+ alarm (10);
+
+ sigfillset (&ss);
+
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st pthread_sigmask failed");
+ _exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ _exit (1);
+ }
+
+ if (pthread_join (th, NULL) != 0)
+ {
+ puts ("thread didn't join");
+ _exit (1);
+ }
+
+ puts ("join succeeded");
+
+ _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+ char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+ int fd = mkstemp (tmp);
+ if (fd == -1)
+ {
+ puts ("mkstemp failed");
+ exit (1);
+ }
+
+ unlink (tmp);
+
+ int i;
+ for (i = 0; i < 20; ++i)
+ write (fd, "foobar xyzzy", 12);
+
+ b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ {
+ puts ("mmap failed");
+ exit (1);
+ }
+
+ pthread_barrierattr_t ba;
+ if (pthread_barrierattr_init (&ba) != 0)
+ {
+ puts ("barrierattr_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+ {
+ puts ("barrierattr_setpshared failed");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (b, &ba, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (pthread_barrierattr_destroy (&ba) != 0)
+ {
+ puts ("barrierattr_destroy failed");
+ exit (1);
+ }
+
+ pid_t pid = fork ();
+ if (pid == -1)
+ {
+ puts ("fork failed");
+ exit (1);
+ }
+
+ if (pid == 0)
+ receiver ();
+
+ pthread_barrier_wait (b);
+
+ /* Wait a bit more. */
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+ nanosleep (&ts, NULL);
+
+ /* Send the signal. */
+ puts ("sending the signal now");
+ kill (pid, SIGINT);
+
+ /* Wait for the process to terminate. */
+ int status;
+ if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+ {
+ puts ("wrong child reported terminated");
+ exit (1);
+ }
+
+ if (!WIFEXITED (status))
+ {
+ if (WIFSIGNALED (status))
+ printf ("child exited with signal %d\n", WTERMSIG (status));
+ else
+ puts ("child didn't exit normally");
+ exit (1);
+ }
+
+ if (WEXITSTATUS (status) != 0)
+ {
+ printf ("exit status %d != 0\n", WEXITSTATUS (status));
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-signal4.c b/test/nptl/tst-signal4.c
new file mode 100644
index 000000000..dcb2893a0
--- /dev/null
+++ b/test/nptl/tst-signal4.c
@@ -0,0 +1,60 @@
+/* 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>
+
+static int
+do_test (void)
+{
+ sigset_t ss;
+
+ sigemptyset (&ss);
+
+ int i;
+ for (i = 0; i < 10000; ++i)
+ {
+ long int r = random ();
+
+ if (r != SIG_BLOCK && r != SIG_SETMASK && r != SIG_UNBLOCK)
+ {
+ int e = pthread_sigmask (r, &ss, NULL);
+
+ if (e == 0)
+ {
+ printf ("pthread_sigmask succeeded for how = %ld\n", r);
+ exit (1);
+ }
+
+ if (e != EINVAL)
+ {
+ puts ("pthread_sigmask didn't return EINVAL");
+ exit (1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-signal5.c b/test/nptl/tst-signal5.c
new file mode 100644
index 000000000..cea6ec143
--- /dev/null
+++ b/test/nptl/tst-signal5.c
@@ -0,0 +1,111 @@
+/* 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 <unistd.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+
+static sigset_t ss;
+
+
+static void *
+tf (void *arg)
+{
+ sigset_t ss2;
+ if (pthread_sigmask (SIG_SETMASK, NULL, &ss2) != 0)
+ {
+ puts ("child: sigmask failed");
+ exit (1);
+ }
+
+ int i;
+ for (i = 1; i < 32; ++i)
+ if (sigismember (&ss, i) && ! sigismember (&ss2, i))
+ {
+ printf ("signal %d set in parent mask, but not in child\n", i);
+ exit (1);
+ }
+ else if (! sigismember (&ss, i) && sigismember (&ss2, i))
+ {
+ printf ("signal %d set in child mask, but not in parent\n", i);
+ exit (1);
+ }
+
+ return NULL;
+}
+
+
+static int
+do_test (void)
+{
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR1);
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("1st sigmask failed");
+ exit (1);
+ }
+
+ pthread_t th;
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("1st create failed");
+ exit (1);
+ }
+
+ void *r;
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("1st join failed");
+ exit (1);
+ }
+
+ sigemptyset (&ss);
+ sigaddset (&ss, SIGUSR2);
+ sigaddset (&ss, SIGFPE);
+ if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+ {
+ puts ("2nd sigmask failed");
+ exit (1);
+ }
+
+ if (pthread_create (&th, NULL, tf, NULL) != 0)
+ {
+ puts ("2nd create failed");
+ exit (1);
+ }
+
+ if (pthread_join (th, &r) != 0)
+ {
+ puts ("2nd join failed");
+ exit (1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls1.c b/test/nptl/tst-tls1.c
new file mode 100644
index 000000000..541035ea7
--- /dev/null
+++ b/test/nptl/tst-tls1.c
@@ -0,0 +1,122 @@
+/* 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 <tls.h>
+
+#if HAVE___THREAD
+struct test_s
+{
+ int a;
+ int b;
+};
+
+#define INIT_A 1
+#define INIT_B 42
+/* Deliberately not static. */
+__thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
+{
+ .a = INIT_A,
+ .b = INIT_B
+};
+
+
+static void *
+tf (void *arg)
+{
+ if (s.a != INIT_A || s.b != INIT_B)
+ {
+ puts ("initial value of s in child thread wrong");
+ exit (1);
+ }
+
+ ++s.a;
+
+ return NULL;
+}
+#endif
+
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+ puts ("No __thread support in compiler, test skipped.");
+
+ return 0;
+#else
+
+ if (s.a != INIT_A || s.b != INIT_B)
+ {
+ puts ("initial value of s in main thread wrong");
+ 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;
+ }
+
+#define N 10
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+#define M 10
+ pthread_t th[M];
+ int j;
+ for (j = 0; j < M; ++j, ++s.a)
+ if (pthread_create (&th[j], &a, tf, NULL) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ for (j = 0; j < M; ++j)
+ if (pthread_join (th[j], NULL) != 0)
+ {
+ puts ("pthread_join failed");
+ exit (1);
+ }
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+#endif
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls2.c b/test/nptl/tst-tls2.c
new file mode 100644
index 000000000..3615d1b81
--- /dev/null
+++ b/test/nptl/tst-tls2.c
@@ -0,0 +1,216 @@
+/* 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 <signal.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void \
+cb##n (void) \
+{ \
+ if (th[n] != pthread_self ()) \
+ { \
+ write (STDOUT_FILENO, "wrong callback\n", 15); \
+ _exit (1); \
+ } \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+ cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
+
+
+static sem_t s;
+
+
+#define THE_SIG SIGUSR1
+static void
+handler (int sig)
+{
+ if (sig != THE_SIG)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ fp ();
+
+ if (sem_post (&s) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+static pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+static int nsigs;
+
+
+static void *
+tf (void *arg)
+{
+ fp = arg;
+
+ pthread_barrier_wait (&b);
+
+ pthread_barrier_wait (&b);
+
+ if (nsigs != TOTAL_SIGS)
+ {
+ puts ("barrier_wait prematurely returns");
+ exit (1);
+ }
+
+ return NULL;
+}
+#endif
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+ puts ("No __thread support in compiler, test skipped.");
+
+ return 0;
+#else
+
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = handler;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (THE_SIG, &sa, NULL) != 0)
+ {
+ puts ("sigaction 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;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ if (pthread_attr_destroy (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ pthread_barrier_wait (&b);
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, THE_SIG);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ /* Start sending signals. */
+ for (i = 0; i < TOTAL_SIGS; ++i)
+ {
+ if (kill (getpid (), THE_SIG) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+
+ ++nsigs;
+ }
+
+ pthread_barrier_wait (&b);
+
+ for (i = 0; i < N; ++i)
+ if (pthread_join (th[i], NULL) != 0)
+ {
+ puts ("join failed");
+ exit (1);
+ }
+
+ return 0;
+#endif
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls3.c b/test/nptl/tst-tls3.c
new file mode 100644
index 000000000..411acbdf0
--- /dev/null
+++ b/test/nptl/tst-tls3.c
@@ -0,0 +1,216 @@
+/* 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 <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthreaddef.h>
+#include <tls.h>
+
+#define THE_SIG SIGUSR1
+
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void \
+cb##n (void) \
+{ \
+ if (th[n] != pthread_self ()) \
+ { \
+ write (STDOUT_FILENO, "wrong callback\n", 15); \
+ _exit (1); \
+ } \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+ cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+sem_t s;
+
+
+pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+int nsigs;
+
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+ puts ("No __thread support in compiler, test skipped.");
+
+ return 0;
+#else
+
+ if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+ {
+ puts ("initial thread's struct pthread not aligned enough");
+ exit (1);
+ }
+
+ if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+ {
+ puts ("barrier_init failed");
+ exit (1);
+ }
+
+ if (sem_init (&s, 0, 0) != 0)
+ {
+ puts ("sem_init failed");
+ exit (1);
+ }
+
+ void *h = dlopen ("tst-tls3mod.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen failed");
+ exit (1);
+ }
+
+ void *(*tf) (void *) = dlsym (h, "tf");
+ if (tf == NULL)
+ {
+ puts ("dlsym for tf failed");
+ exit (1);
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = dlsym (h, "handler");
+ if (sa.sa_handler == NULL)
+ {
+ puts ("dlsym for handler failed");
+ exit (1);
+ }
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (sigaction (THE_SIG, &sa, NULL) != 0)
+ {
+ puts ("sigaction 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;
+ }
+
+ int r;
+ for (r = 0; r < 10; ++r)
+ {
+ int i;
+ for (i = 0; i < N; ++i)
+ if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+ {
+ puts ("pthread_create failed");
+ exit (1);
+ }
+
+ nsigs = 0;
+
+ pthread_barrier_wait (&b);
+
+ sigset_t ss;
+ sigemptyset (&ss);
+ sigaddset (&ss, THE_SIG);
+ if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask failed");
+ exit (1);
+ }
+
+ /* Start sending signals. */
+ for (i = 0; i < TOTAL_SIGS; ++i)
+ {
+ if (kill (getpid (), THE_SIG) != 0)
+ {
+ puts ("kill failed");
+ exit (1);
+ }
+
+ if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+ {
+ puts ("sem_wait failed");
+ exit (1);
+ }
+
+ ++nsigs;
+ }
+
+ pthread_barrier_wait (&b);
+
+ if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
+ {
+ puts ("pthread_sigmask 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 (&a) != 0)
+ {
+ puts ("attr_destroy failed");
+ exit (1);
+ }
+
+ return 0;
+#endif
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls3mod.c b/test/nptl/tst-tls3mod.c
new file mode 100644
index 000000000..25f892405
--- /dev/null
+++ b/test/nptl/tst-tls3mod.c
@@ -0,0 +1,94 @@
+/* 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 <semaphore.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthreaddef.h>
+#include <tls.h>
+
+#if HAVE___THREAD
+
+extern pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+extern int nsigs;
+
+extern sem_t s;
+
+
+static __thread void (*fp) (void);
+
+
+#define THE_SIG SIGUSR1
+void
+handler (int sig)
+{
+ if (sig != THE_SIG)
+ {
+ write (STDOUT_FILENO, "wrong signal\n", 13);
+ _exit (1);
+ }
+
+ fp ();
+
+ if (sem_post (&s) != 0)
+ {
+ write (STDOUT_FILENO, "sem_post failed\n", 16);
+ _exit (1);
+ }
+}
+
+
+void *
+tf (void *arg)
+{
+ if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+ {
+ puts ("thread's struct pthread not aligned enough");
+ exit (1);
+ }
+
+ if (fp != NULL)
+ {
+printf("fp=%p\n", (void *)&fp);
+ puts ("fp not initially NULL");
+ exit (1);
+ }
+
+ fp = arg;
+
+ pthread_barrier_wait (&b);
+
+ pthread_barrier_wait (&b);
+
+ if (nsigs != TOTAL_SIGS)
+ {
+ puts ("barrier_wait prematurely returns");
+ exit (1);
+ }
+
+ return NULL;
+}
+
+#endif
diff --git a/test/nptl/tst-tls4.c b/test/nptl/tst-tls4.c
new file mode 100644
index 000000000..52775dee8
--- /dev/null
+++ b/test/nptl/tst-tls4.c
@@ -0,0 +1,191 @@
+/* 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 <dlfcn.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+#define N 3
+
+void (*test1) (void), (*test2) (void);
+
+pthread_barrier_t b2, b3;
+
+static void *
+tf (void *arg)
+{
+ int i;
+
+ for (i = 0; i <= (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test1 ();
+
+ for (i = 0; i < 3; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ test2 ();
+
+ for (i = 0; i < 3 - (uintptr_t) arg; ++i)
+ {
+ int r = pthread_barrier_wait (&b3);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf: barrier_wait failed");
+ exit (1);
+ }
+ }
+
+ return NULL;
+}
+
+static void *
+tf2 (void *arg)
+{
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("tf2: barrier_wait failed");
+ exit (1);
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ tf (arg);
+ return NULL;
+}
+
+int
+do_test (void)
+{
+ pthread_t th[2];
+ const char *modules[N]
+ = { "tst-tls4moda.so", "tst-tls4moda.so", "tst-tls4modb.so" };
+
+ if (pthread_barrier_init (&b2, NULL, 2) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_barrier_init (&b3, NULL, 3) != 0)
+ {
+ puts ("barrier_init failed");
+ return 1;
+ }
+
+ if (pthread_create (&th[0], NULL, tf2, (void *) (uintptr_t) 1))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ puts ("barrier_wait failed");
+ return 1;
+ }
+
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ void *h = dlopen (modules[i], RTLD_LAZY);
+ if (h == NULL)
+ {
+ printf ("dlopen failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test1 = dlsym (h, "test1");
+ if (test1 == NULL)
+ {
+ printf ("dlsym for test1 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ test2 = dlsym (h, "test2");
+ if (test2 == NULL)
+ {
+ printf ("dlsym for test2 failed %s\n", dlerror ());
+ return 1;
+ }
+
+ if (pthread_create (&th[1], NULL, tf, (void *) (uintptr_t) 2))
+ {
+ puts ("pthread_create failed");
+ return 1;
+ }
+
+ tf ((void *) (uintptr_t) 0);
+
+ if (pthread_join (th[1], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ if (dlclose (h))
+ {
+ puts ("dlclose failed");
+ return 1;
+ }
+
+ printf ("test %d with %s succeeded\n", i, modules[i]);
+ }
+
+ if (pthread_join (th[0], NULL) != 0)
+ {
+ puts ("join failed");
+ return 1;
+ }
+
+ return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls4moda.c b/test/nptl/tst-tls4moda.c
new file mode 100644
index 000000000..ff7ee5604
--- /dev/null
+++ b/test/nptl/tst-tls4moda.c
@@ -0,0 +1,56 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static __thread unsigned char foo [32]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))));
+
+void
+test1 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = s;
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo); ++s)
+ {
+ if (foo [s] != s)
+ abort ();
+ foo [s] = sizeof (foo) - s;
+ }
+}
+
+#endif
diff --git a/test/nptl/tst-tls4modb.c b/test/nptl/tst-tls4modb.c
new file mode 100644
index 000000000..99f3b5405
--- /dev/null
+++ b/test/nptl/tst-tls4modb.c
@@ -0,0 +1,65 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tls.h>
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static int i;
+int bar;
+
+static __thread void *foo [32 / sizeof (void *)]
+ __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))))
+ = { &i, &bar };
+
+void
+test1 (void)
+{
+ size_t s;
+
+ if (foo [0] != &i || foo [1] != &bar)
+ abort ();
+
+ foo [0] = NULL;
+ foo [1] = NULL;
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s])
+ abort ();
+ foo [s] = &foo[s];
+ }
+}
+
+void
+test2 (void)
+{
+ size_t s;
+
+ for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+ {
+ if (foo [s] != &foo [s])
+ abort ();
+ foo [s] = &foo [s ^ 1];
+ }
+}
+
+#endif
diff --git a/test/nptl/tst-tls5.c b/test/nptl/tst-tls5.c
new file mode 100644
index 000000000..546253256
--- /dev/null
+++ b/test/nptl/tst-tls5.c
@@ -0,0 +1,120 @@
+/* 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. */
+
+/* Check alignment, overlapping and layout of TLS variables. */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <pthreadP.h>
+#include <sys/param.h>
+
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+
+struct tls_obj tls_registry[64];
+
+static int
+tls_addr_cmp (const void *a, const void *b)
+{
+ if (((struct tls_obj *)a)->addr < ((struct tls_obj *)b)->addr)
+ return -1;
+ if (((struct tls_obj *)a)->addr > ((struct tls_obj *)b)->addr)
+ return 1;
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ size_t cnt, i;
+ int res = 0;
+ uintptr_t min_addr = ~(uintptr_t) 0, max_addr = 0;
+
+ for (cnt = 0; tls_registry[cnt].name; ++cnt);
+ tls_registry[cnt].name = NULL;
+ tls_registry[cnt].addr = (uintptr_t) pthread_self ();
+ tls_registry[cnt].size = sizeof (struct pthread);
+ tls_registry[cnt++].align = __alignof__ (struct pthread);
+
+ qsort (tls_registry, cnt, sizeof (struct tls_obj), tls_addr_cmp);
+
+ for (i = 0; i < cnt; ++i)
+ {
+ printf ("%s%s = %p, size %zd, align %zd",
+ tls_registry[i].name ? "&" : "",
+ tls_registry[i].name ?: "pthread_self ()",
+ (void *) tls_registry[i].addr,
+ tls_registry[i].size, tls_registry[i].align);
+ if (tls_registry[i].addr & (tls_registry[i].align - 1))
+ {
+ fputs (", WRONG ALIGNMENT", stdout);
+ res = 1;
+ }
+ if (i > 0
+ && (tls_registry[i - 1].addr + tls_registry[i - 1].size
+ > tls_registry[i].addr))
+ {
+ fputs (", ADDRESS OVERLAP", stdout);
+ res = 1;
+ }
+ puts ("");
+ if (tls_registry[i].name)
+ {
+ min_addr = MIN (tls_registry[i].addr, min_addr);
+ max_addr = MAX (tls_registry[i].addr + tls_registry[i].size,
+ max_addr);
+ }
+ }
+
+ if (cnt > 1)
+ {
+#if TLS_TCB_AT_TP
+ if (tls_registry[cnt - 1].name)
+ {
+ puts ("pthread_self () not larger than all TLS addresses");
+ res = 1;
+ }
+ else
+ max_addr = MAX (tls_registry[cnt - 1].addr, max_addr);
+#elif TLS_DTV_AT_TP
+ if (tls_registry[0].name)
+ {
+ puts ("pthread_self () not smaller than all TLS addresses");
+ res = 1;
+ }
+#else
+ abort ();
+#endif
+ printf ("Initial TLS used block size %zd\n",
+ (size_t) (max_addr - min_addr));
+ }
+ return res;
+}
+
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/test/nptl/tst-tls5.h b/test/nptl/tst-tls5.h
new file mode 100644
index 000000000..b7c14eb82
--- /dev/null
+++ b/test/nptl/tst-tls5.h
@@ -0,0 +1,28 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <tls.h>
+
+#if USE_TLS && HAVE___THREAD
+
+struct tls_obj
+{
+ const char *name;
+ uintptr_t addr;
+ size_t size;
+ size_t align;
+};
+extern struct tls_obj tls_registry[];
+
+#define TLS_REGISTER(x) \
+static void __attribute__((constructor)) \
+tls_register_##x (void) \
+{ \
+ size_t i; \
+ for (i = 0; tls_registry[i].name; ++i); \
+ tls_registry[i].name = #x; \
+ tls_registry[i].addr = (uintptr_t) &x; \
+ tls_registry[i].size = sizeof (x); \
+ tls_registry[i].align = __alignof__ (x); \
+}
+
+#endif
diff --git a/test/nptl/tst-tls5mod.c b/test/nptl/tst-tls5mod.c
new file mode 100644
index 000000000..b308bd60e
--- /dev/null
+++ b/test/nptl/tst-tls5mod.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+/* Ensure tls_registry is exported from the binary. */
+void *tst_tls5mod attribute_hidden = tls_registry;
+#endif
diff --git a/test/nptl/tst-tls5moda.c b/test/nptl/tst-tls5moda.c
new file mode 100644
index 000000000..a035c96cd
--- /dev/null
+++ b/test/nptl/tst-tls5moda.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread char a [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (a)
+#endif
diff --git a/test/nptl/tst-tls5modb.c b/test/nptl/tst-tls5modb.c
new file mode 100644
index 000000000..848a80363
--- /dev/null
+++ b/test/nptl/tst-tls5modb.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int b;
+TLS_REGISTER (b)
+#endif
diff --git a/test/nptl/tst-tls5modc.c b/test/nptl/tst-tls5modc.c
new file mode 100644
index 000000000..d63ceff8d
--- /dev/null
+++ b/test/nptl/tst-tls5modc.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int c;
+TLS_REGISTER (c)
+#endif
diff --git a/test/nptl/tst-tls5modd.c b/test/nptl/tst-tls5modd.c
new file mode 100644
index 000000000..202a66a15
--- /dev/null
+++ b/test/nptl/tst-tls5modd.c
@@ -0,0 +1,6 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int d;
+TLS_REGISTER (d)
+#endif
diff --git a/test/nptl/tst-tls5mode.c b/test/nptl/tst-tls5mode.c
new file mode 100644
index 000000000..3e53ee1a6
--- /dev/null
+++ b/test/nptl/tst-tls5mode.c
@@ -0,0 +1,8 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+static __thread int e1 = 24;
+static __thread char e2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (e1)
+TLS_REGISTER (e2)
+#endif
diff --git a/test/nptl/tst-tls5modf.c b/test/nptl/tst-tls5modf.c
new file mode 100644
index 000000000..8e50962de
--- /dev/null
+++ b/test/nptl/tst-tls5modf.c
@@ -0,0 +1,9 @@
+#include <tst-tls5.h>
+
+#ifdef TLS_REGISTER
+char tst_tls5modf[60] attribute_hidden = { 26 };
+static __thread int f1 = 24;
+static __thread char f2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (f1)
+TLS_REGISTER (f2)
+#endif
diff --git a/test/nptl/tst-tls6.sh b/test/nptl/tst-tls6.sh
new file mode 100755
index 000000000..22d094a75
--- /dev/null
+++ b/test/nptl/tst-tls6.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+logfile=tst-tls6.out
+
+LC_ALL=C
+export LC_ALL
+LANG=C
+export LANG
+
+> $logfile
+fail=0
+
+for aligned in a e f; do
+ echo "preload tst-tls5mod{$aligned,b,c,d}.so" >> $logfile
+ echo "===============" >> $logfile
+ LD_PRELOAD=`echo tst-tls5mod{$aligned,b,c,d}.so \
+ | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+
+ echo "preload tst-tls5mod{b,$aligned,c,d}.so" >> $logfile
+ echo "===============" >> $logfile
+ LD_PRELOAD=`echo tst-tls5mod{b,$aligned,c,d}.so \
+ | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+
+ echo "preload tst-tls5mod{b,c,d,$aligned}.so" >> $logfile
+ echo "===============" >> $logfile
+ LD_PRELOAD=`echo tst-tls5mod{b,c,d,$aligned}.so \
+ | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+ echo >> $logfile
+done
+
+echo "preload tst-tls5mod{d,a,b,c,e}" >> $logfile
+echo "===============" >> $logfile
+LD_PRELOAD=`echo tst-tls5mod{d,a,b,c,e}.so \
+ | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+echo >> $logfile
+
+echo "preload tst-tls5mod{d,a,b,e,f}" >> $logfile
+echo "===============" >> $logfile
+LD_PRELOAD=`echo tst-tls5mod{d,a,b,e,f}.so \
+ | sed 's/:$//;s/: /:/g'` ${tst_tls5} >> $logfile || fail=1
+echo >> $logfile
+
+exit $fail