about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-06-07 02:03:45 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-06-07 13:35:54 +0200
commitd6d74ec16c77126c59db264ebfa04d08d5b4c5c0 (patch)
tree95fded09b6a9d8ce35273d43c3f8e3d960bd0554 /sysdeps
parentbe22a151f3e2c2e4b9127d4fa30b269f30a7ea2e (diff)
downloadglibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.tar.gz
glibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.tar.xz
glibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.zip
htl: Enable more tests
* htl/Makefile: Remove rules adding libpthread.so and libpthread.a to link
lines.
* nptl/Makefile: Move rules adding libpthread.so and libpthread.a to
link lines to...
* sysdeps/pthread/Makefile: ... here.

* nptl/eintr.c, tst-align.c tst-align3.c tst-atfork1.c tst-backtrace1.c
tst-bad-schedattr.c tst-cancel-self-canceltype.c tst-cancel-self-cleanup.c
tst-cancel-self-testcancel.c tst-cancel1.c tst-cancel10.c tst-cancel12.c
tst-cancel14.c tst-cancel15.c tst-cancel18.c tst-cancel19.c tst-cancel2.c
tst-cancel22.c tst-cancel23.c tst-cancel26.c tst-cancel27.c tst-cancel28.c
tst-cancel3.c tst-cancel8.c tst-cancelx1.c tst-cancelx10.c tst-cancelx12.c
tst-cancelx14.c tst-cancelx15.c tst-cancelx18.c tst-cancelx2.c tst-cancelx3.c
tst-cancelx8.c tst-cleanup0.c tst-cleanup0.expect tst-cleanup1.c tst-cleanup2.c
tst-cleanup3.c tst-cleanupx0.c tst-cleanupx0.expect tst-cleanupx1.c
tst-cleanupx2.c tst-cleanupx3.c tst-clock1.c tst-create-detached.c tst-detach1.c
tst-eintr2.c tst-eintr3.c tst-eintr4.c tst-eintr5.c tst-exec1.c tst-exec2.c
tst-exec3.c tst-exit1.c tst-exit2.c tst-exit3.c tst-flock1.c tst-fork1.c
tst-fork2.c tst-fork3.c tst-fork4.c tst-getpid3.c tst-kill1.c tst-kill2.c
tst-kill3.c tst-kill4.c tst-kill5.c tst-kill6.c tst-locale1.c tst-locale2.c
tst-memstream.c tst-popen1.c tst-raise1.c tst-sem5.c tst-setuid3.c tst-signal4.c
tst-signal5.c tst-signal6.c tst-signal8.c tst-stack1.c tst-stdio1.c tst-stdio2.c
tst-sysconf.c tst-tls1.c tst-tls2.c tst-tsd1.c tst-tsd2.c tst-tsd5.c tst-tsd6.c
tst-umask1.c tst-unload.c tst-unwind-thread.c tst-vfork1.c tst-vfork1x.c
tst-vfork2.c tst-vfork2x.c: Move tests to...
* sysdeps/pthread: ... here.
Rename
tst-popen1.c -> tst-pt-popen1.c
tst-align.c -> tst-pt-align.c
tst-align3.c -> tst-pt-align3.c
tst-sysconf.c -> tst-pt-sysconf.c
tst-tls1.c -> tst-pt-tls1.c
tst-tls2.c -> tst-pt-tls2.c
tst-vfork1.c -> tst-pt-vfork1.c
tst-vfork2.c -> tst-pt-vfork2.c
to avoid conflicting with libio/tst-popen1.c, elf/tst-align.c,
posix/tst-sysconf.c, elf/tst-tls1.c, elf/tst-tls2.c, posix/tst-vfork1.c,
posix/tst-vfork2.c.

* nptl/Makefile: Move corresponding tests references and special rules to...
* sysdeps/pthread/Makefile: ... here.

* sysdeps/pthread/tst-stack1.c (do_test): Do not clamp stack size to
PTHREAD_STACK_MIN if not defined.

Tested on linux-x86_64 and hurd-i386
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/pthread/Makefile120
-rw-r--r--sysdeps/pthread/eintr.c86
-rw-r--r--sysdeps/pthread/tst-atfork1.c120
-rw-r--r--sysdeps/pthread/tst-backtrace1.c85
-rw-r--r--sysdeps/pthread/tst-bad-schedattr.c97
-rw-r--r--sysdeps/pthread/tst-cancel-self-canceltype.c53
-rw-r--r--sysdeps/pthread/tst-cancel-self-cleanup.c23
-rw-r--r--sysdeps/pthread/tst-cancel-self-testcancel.c48
-rw-r--r--sysdeps/pthread/tst-cancel1.c162
-rw-r--r--sysdeps/pthread/tst-cancel10.c125
-rw-r--r--sysdeps/pthread/tst-cancel12.c123
-rw-r--r--sysdeps/pthread/tst-cancel14.c133
-rw-r--r--sysdeps/pthread/tst-cancel15.c138
-rw-r--r--sysdeps/pthread/tst-cancel18.c173
-rw-r--r--sysdeps/pthread/tst-cancel19.c285
-rw-r--r--sysdeps/pthread/tst-cancel2.c95
-rw-r--r--sysdeps/pthread/tst-cancel22.c119
-rw-r--r--sysdeps/pthread/tst-cancel23.c1
-rw-r--r--sysdeps/pthread/tst-cancel26.c68
-rw-r--r--sysdeps/pthread/tst-cancel27.c23
-rw-r--r--sysdeps/pthread/tst-cancel28.c79
-rw-r--r--sysdeps/pthread/tst-cancel3.c97
-rw-r--r--sysdeps/pthread/tst-cancel8.c142
-rw-r--r--sysdeps/pthread/tst-cancelx1.c1
-rw-r--r--sysdeps/pthread/tst-cancelx10.c1
-rw-r--r--sysdeps/pthread/tst-cancelx12.c1
-rw-r--r--sysdeps/pthread/tst-cancelx14.c1
-rw-r--r--sysdeps/pthread/tst-cancelx15.c1
-rw-r--r--sysdeps/pthread/tst-cancelx18.c1
-rw-r--r--sysdeps/pthread/tst-cancelx2.c1
-rw-r--r--sysdeps/pthread/tst-cancelx3.c1
-rw-r--r--sysdeps/pthread/tst-cancelx8.c1
-rw-r--r--sysdeps/pthread/tst-cleanup0.c74
-rw-r--r--sysdeps/pthread/tst-cleanup0.expect3
-rw-r--r--sysdeps/pthread/tst-cleanup1.c100
-rw-r--r--sysdeps/pthread/tst-cleanup2.c63
-rw-r--r--sysdeps/pthread/tst-cleanup3.c98
-rw-r--r--sysdeps/pthread/tst-cleanupx0.c1
-rw-r--r--sysdeps/pthread/tst-cleanupx0.expect3
-rw-r--r--sysdeps/pthread/tst-cleanupx1.c1
-rw-r--r--sysdeps/pthread/tst-cleanupx2.c1
-rw-r--r--sysdeps/pthread/tst-cleanupx3.c1
-rw-r--r--sysdeps/pthread/tst-clock1.c50
-rw-r--r--sysdeps/pthread/tst-cond22.c162
-rw-r--r--sysdeps/pthread/tst-cond26.c77
-rw-r--r--sysdeps/pthread/tst-create-detached.c138
-rw-r--r--sysdeps/pthread/tst-detach1.c55
-rw-r--r--sysdeps/pthread/tst-eintr2.c88
-rw-r--r--sysdeps/pthread/tst-eintr3.c60
-rw-r--r--sysdeps/pthread/tst-eintr4.c48
-rw-r--r--sysdeps/pthread/tst-eintr5.c63
-rw-r--r--sysdeps/pthread/tst-exec1.c156
-rw-r--r--sysdeps/pthread/tst-exec2.c151
-rw-r--r--sysdeps/pthread/tst-exec3.c149
-rw-r--r--sysdeps/pthread/tst-exit1.c78
-rw-r--r--sysdeps/pthread/tst-exit2.c42
-rw-r--r--sysdeps/pthread/tst-exit3.c83
-rw-r--r--sysdeps/pthread/tst-flock1.c92
-rw-r--r--sysdeps/pthread/tst-fork1.c121
-rw-r--r--sysdeps/pthread/tst-fork2.c89
-rw-r--r--sysdeps/pthread/tst-fork3.c108
-rw-r--r--sysdeps/pthread/tst-fork4.c64
-rw-r--r--sysdeps/pthread/tst-getpid3.c114
-rw-r--r--sysdeps/pthread/tst-kill1.c99
-rw-r--r--sysdeps/pthread/tst-kill2.c137
-rw-r--r--sysdeps/pthread/tst-kill3.c158
-rw-r--r--sysdeps/pthread/tst-kill4.c90
-rw-r--r--sysdeps/pthread/tst-kill5.c49
-rw-r--r--sysdeps/pthread/tst-kill6.c162
-rw-r--r--sysdeps/pthread/tst-locale1.c22
-rw-r--r--sysdeps/pthread/tst-locale2.c15
-rw-r--r--sysdeps/pthread/tst-memstream.c101
-rw-r--r--sysdeps/pthread/tst-pt-align.c70
-rw-r--r--sysdeps/pthread/tst-pt-align3.c56
-rw-r--r--sysdeps/pthread/tst-pt-popen1.c59
-rw-r--r--sysdeps/pthread/tst-pt-sysconf.c47
-rw-r--r--sysdeps/pthread/tst-pt-tls1.c119
-rw-r--r--sysdeps/pthread/tst-pt-tls2.c206
-rw-r--r--sysdeps/pthread/tst-pt-vfork1.c1
-rw-r--r--sysdeps/pthread/tst-pt-vfork2.c1
-rw-r--r--sysdeps/pthread/tst-raise1.c61
-rw-r--r--sysdeps/pthread/tst-setuid3.c118
-rw-r--r--sysdeps/pthread/tst-signal4.c59
-rw-r--r--sysdeps/pthread/tst-signal5.c110
-rw-r--r--sysdeps/pthread/tst-signal6.c197
-rw-r--r--sysdeps/pthread/tst-signal8.c62
-rw-r--r--sysdeps/pthread/tst-stack1.c148
-rw-r--r--sysdeps/pthread/tst-stdio1.c56
-rw-r--r--sysdeps/pthread/tst-stdio2.c82
-rw-r--r--sysdeps/pthread/tst-tsd1.c117
-rw-r--r--sysdeps/pthread/tst-tsd2.c96
-rw-r--r--sysdeps/pthread/tst-tsd5.c80
-rw-r--r--sysdeps/pthread/tst-tsd6.c89
-rw-r--r--sysdeps/pthread/tst-umask1.c136
-rw-r--r--sysdeps/pthread/tst-unload.c47
-rw-r--r--sysdeps/pthread/tst-unwind-thread.c2
-rw-r--r--sysdeps/pthread/tst-vfork1x.c1
-rw-r--r--sysdeps/pthread/tst-vfork2x.c1
98 files changed, 7350 insertions, 241 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index 1d1ddeb099..fb78e55e27 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -42,23 +42,48 @@ libpthread-routines += thrd_create thrd_detach thrd_exit thrd_join \
 tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
 	 tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
 	 tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
+	 \
+	 tst-abstime \
+	 tst-pt-align tst-pt-align3 \
 	 tst-attr1 \
+	 tst-backtrace1 \
+	 tst-bad-schedattr \
 	 tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
 	 tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
 	 tst-basic7 \
+	 tst-cancel-self-canceltype tst-cancel-self-testcancel \
+	 tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel8 tst-cancel10 \
+	 tst-cancel12 tst-cancel14 tst-cancel15 tst-cancel18 tst-cancel19 \
+	 tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \
+	 tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
+	 tst-clock1 \
+	 tst-cond-except \
 	 tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
 	 tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
 	 tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
 	 tst-cond20 tst-cond21 tst-cond23 tst-cond24 tst-cond25 tst-cond27 \
-	 tst-cond-except \
+	 tst-create-detached \
+	 tst-detach1 \
+	 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
+	 tst-exec1 tst-exec2 tst-exec3 \
+	 tst-exit1 tst-exit2 tst-exit3 \
+	 tst-flock1 \
+	 tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
+	 tst-atfork1 \
+	 tst-getpid3 \
 	 tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
 	 tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
 	 tst-join14 \
 	 tst-key1 tst-key2 tst-key3 tst-key4 \
+	 tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
+	 tst-locale1 tst-locale2 \
+	 tst-memstream \
 	 tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
 	 tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex7robust tst-mutex9 \
 	 tst-mutex10 tst-mutex11 tst-pthread-mutexattr \
 	 tst-once1 tst-once2 tst-once3 tst-once4 \
+	 tst-pt-popen1 \
+	 tst-raise1 \
 	 tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
 	 tst-robust6 tst-robust7 tst-robust9 tst-robust10 \
 	 tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock12 \
@@ -66,8 +91,79 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
 	 tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
 	 tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
 	 tst-sem8 tst-sem9 tst-sem10 tst-sem14 tst-sem15 tst-sem16 \
+	 tst-setuid3 \
+	 tst-signal4 tst-signal5 tst-signal6 tst-signal8 \
 	 tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
-	 tst-abstime
+	 tst-stack1 \
+	 tst-stdio1 tst-stdio2 \
+	 tst-pt-sysconf \
+	 tst-pt-tls1 tst-pt-tls2 \
+	 tst-tsd1 tst-tsd2 tst-tsd5 tst-tsd6 \
+	 tst-umask1 \
+	 tst-unload \
+	 tst-unwind-thread \
+	 tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
+
+
+# Files which must not be linked with libpthread.
+tests-nolibpthread = tst-unload
+
+# GCC-4.9 compiles 'sprintf(NULL, ...)' into UD2 on x86_64 without -fno-builtin
+CFLAGS-tst-cleanup2.c += -fno-builtin
+CFLAGS-tst-cleanupx2.c += -fno-builtin
+
+tests += tst-cancelx2 tst-cancelx3 tst-cancelx8 tst-cancelx10 \
+	 tst-cancelx12 tst-cancelx14 tst-cancelx15 tst-cancelx18 \
+	 tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
+
+tests-static += tst-locale1 tst-locale2
+
+tests += tst-cond11-static
+
+
+# These tests are linked with libc before libpthread
+tests-reverse += tst-cancel23 tst-vfork1x tst-vfork2x
+
+ifeq ($(run-built-tests),yes)
+ifeq ($(build-shared),yes)
+tests-special += $(objpfx)tst-cleanup0-cmp.out
+endif
+endif
+
+# Run the cancellation and cleanup tests also for the modern, exception-based
+# implementation.  For this we have to pass the -fexceptions parameter.
+CFLAGS-tst-cancelx2.c += -fexceptions
+CFLAGS-tst-cancelx3.c += -fexceptions
+CFLAGS-tst-cancelx8.c += -fexceptions
+CFLAGS-tst-cancelx10.c += -fexceptions
+CFLAGS-tst-cancelx12.c += -fexceptions
+CFLAGS-tst-cancelx14.c += -fexceptions
+CFLAGS-tst-cancelx15.c += -fexceptions
+CFLAGS-tst-cancelx18.c += -fexceptions
+CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables
+CFLAGS-tst-cleanupx2.c += -fexceptions
+CFLAGS-tst-cleanupx3.c += -fexceptions
+CFLAGS-tst-pt-align.c += $(stack-align-test-flags)
+CFLAGS-tst-pt-align3.c += $(stack-align-test-flags)
+
+tst-umask1-ARGS = $(objpfx)tst-umask1.temp
+
+ifeq ($(build-shared),yes)
+$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
+	$(make-test-out) > $@ 2>&1; \
+	$(evaluate-test)
+
+$(objpfx)tst-cleanup0-cmp.out: $(..)sysdeps/pthread/tst-cleanup0.expect $(objpfx)tst-cleanup0.out
+	cmp $^ > $@; \
+	$(evaluate-test)
+
+$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.so
+else
+$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.a
+endif
+
+
 
 tests-internal += tst-robust8
 
@@ -88,4 +184,24 @@ $(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
 $(objpfx)tst-join7mod.so: $(shared-thread-library)
 LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
 
+CFLAGS-tst-unwind-thread.c += -funwind-tables
+
+# Make sure we link with the thread library.
+ifeq ($(build-shared),yes)
+$(addprefix $(objpfx), \
+  $(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \
+    $(tests-nolibpthread), \
+    $(tests) $(tests-internal) $(xtests) $(test-srcs) $(tests-container))): \
+	$(objpfx)libpthread.so
+$(objpfx)tst-unload: $(libdl)
+# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
+# since otherwise libpthread.so comes before libc.so when linking.
+$(addprefix $(objpfx), $(tests-reverse)): \
+  $(objpfx)../libc.so $(objpfx)libpthread.so
+$(objpfx)../libc.so: $(common-objpfx)libc.so ;
+$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
+else
+$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
+endif
+
 endif
diff --git a/sysdeps/pthread/eintr.c b/sysdeps/pthread/eintr.c
new file mode 100644
index 0000000000..99a03e0957
--- /dev/null
+++ b/sysdeps/pthread/eintr.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <unistd.h>
+#include <support/xthread.h>
+#include <support/xsignal.h>
+#include <support/xthread.h>
+
+
+static int the_sig;
+
+
+static void
+eintr_handler (int sig)
+{
+  if (sig != the_sig)
+    {
+      write (STDOUT_FILENO, "eintr_handler: signal number wrong\n", 35);
+      _exit (1);
+    }
+  write (STDOUT_FILENO, ".", 1);
+}
+
+
+static void *
+eintr_source (void *arg)
+{
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000 };
+
+  if (arg == NULL)
+    {
+      sigset_t ss;
+      sigemptyset (&ss);
+      sigaddset (&ss, the_sig);
+      xpthread_sigmask (SIG_BLOCK, &ss, NULL);
+    }
+
+  while (1)
+    {
+      if (arg != NULL)
+	pthread_kill (*(pthread_t *) arg, the_sig);
+      else
+	kill (getpid (), the_sig);
+
+      nanosleep (&ts, NULL);
+    }
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static void
+setup_eintr (int sig, pthread_t *thp)
+{
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = eintr_handler;
+  if (sigaction (sig, &sa, NULL) != 0)
+    {
+      puts ("setup_eintr: sigaction failed");
+      exit (1);
+    }
+  the_sig = sig;
+
+  /* Create the thread which will fire off the signals.  */
+  xpthread_create (NULL, eintr_source, thp);
+}
diff --git a/sysdeps/pthread/tst-atfork1.c b/sysdeps/pthread/tst-atfork1.c
new file mode 100644
index 0000000000..b7d2c023df
--- /dev/null
+++ b/sysdeps/pthread/tst-atfork1.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static int val;
+
+
+static void
+prepare1 (void)
+{
+  val *= 2;
+}
+
+static void
+prepare2 (void)
+{
+  ++val;
+}
+
+static void
+parent1 (void)
+{
+  val += 4;
+}
+
+static void
+parent2 (void)
+{
+  val *= 4;
+}
+
+static void
+child1 (void)
+{
+  val += 8;
+}
+
+static void
+child2 (void)
+{
+  val *= 8;
+}
+
+
+static int
+do_test (void)
+{
+  pid_t pid;
+  int status = 0;
+
+  if (pthread_atfork (prepare1, parent1, child1) != 0)
+    {
+      puts ("1st atfork failed");
+      exit (1);
+    }
+  if (pthread_atfork (prepare2, parent2, child2) != 0)
+    {
+      puts ("2nd atfork failed");
+      exit (1);
+    }
+
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid != 0)
+    {
+      /* Parent.  */
+      if (val != 24)
+	{
+	  printf ("expected val=%d, got %d\n", 24, val);
+	  exit (1);
+	}
+
+      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+	{
+	  puts ("waitpid failed");
+	  exit (1);
+	}
+    }
+  else
+    {
+      /* Child.  */
+      if (val != 80)
+	{
+	  printf ("expected val=%d, got %d\n", 80, val);
+	  exit (2);
+	}
+    }
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-backtrace1.c b/sysdeps/pthread/tst-backtrace1.c
new file mode 100644
index 0000000000..9c7efd306a
--- /dev/null
+++ b/sysdeps/pthread/tst-backtrace1.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 2004-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <execinfo.h>
+#include <pthread.h>
+#include <stdio.h>
+
+#define BT_SIZE 64
+void *bt_array[BT_SIZE];
+int bt_cnt;
+
+int
+do_bt (void)
+{
+  bt_cnt = backtrace (bt_array, BT_SIZE);
+  return 56;
+}
+
+int
+call_do_bt (void)
+{
+  return do_bt () + 1;
+}
+
+void *
+tf (void *arg)
+{
+  if (call_do_bt () != 57)
+    return (void *) 1L;
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL))
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res))
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != NULL)
+    {
+      puts ("thread failed");
+      return 1;
+    }
+
+  char **text = backtrace_symbols (bt_array, bt_cnt);
+  if (text == NULL)
+    {
+      puts ("backtrace_symbols failed");
+      return 1;
+    }
+
+  for (int i = 0; i < bt_cnt; ++i)
+    puts (text[i]);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-bad-schedattr.c b/sysdeps/pthread/tst-bad-schedattr.c
new file mode 100644
index 0000000000..f837dbdc76
--- /dev/null
+++ b/sysdeps/pthread/tst-bad-schedattr.c
@@ -0,0 +1,97 @@
+/* Test that pthread_create diagnoses invalid scheduling parameters.
+   Copyright (C) 2014-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static void *
+thread_function (void *arg)
+{
+  abort ();
+}
+
+
+static int
+do_test (void)
+{
+#if !defined SCHED_FIFO || !defined SCHED_OTHER
+  puts ("SCHED_FIFO or SCHED_OTHER not available at compile time");
+  return 0; /* 77 */
+#else
+
+  int err;
+
+#define TRY(func, arglist)                              \
+  if ((err = func arglist) != 0)                        \
+    {                                                   \
+      printf ("%s: %s\n", #func, strerror (err));       \
+      return 2;                                         \
+    }
+
+  int fifo_max = sched_get_priority_max (SCHED_FIFO);
+  if (fifo_max == -1)
+    {
+      assert (errno == ENOTSUP || errno == ENOSYS);
+      puts ("SCHED_FIFO not supported, cannot test");
+      return 0; /* 77 */
+    }
+
+  int other_max = sched_get_priority_max (SCHED_OTHER);
+  if (other_max == -1)
+    {
+      assert (errno == ENOTSUP || errno == ENOSYS);
+      puts ("SCHED_OTHER not supported, cannot test");
+      return 0; /* 77 */
+    }
+
+  assert (fifo_max > other_max);
+
+  pthread_attr_t attr;
+  TRY (pthread_attr_init, (&attr));
+  TRY (pthread_attr_setinheritsched, (&attr, PTHREAD_EXPLICIT_SCHED));
+  TRY (pthread_attr_setschedpolicy, (&attr, SCHED_FIFO));
+
+  /* This value is chosen so as to be valid for SCHED_FIFO but invalid for
+     SCHED_OTHER.  */
+  struct sched_param param = { .sched_priority = other_max + 1 };
+  TRY (pthread_attr_setschedparam, (&attr, &param));
+
+  TRY (pthread_attr_setschedpolicy, (&attr, SCHED_OTHER));
+
+  /* Now ATTR has a sched_param that is invalid for its policy.  */
+  pthread_t th;
+  err = pthread_create (&th, &attr, &thread_function, NULL);
+  if (err != EINVAL)
+    {
+      printf ("pthread_create returned %d (%s), expected %d (EINVAL: %s)\n",
+              err, strerror (err), EINVAL, strerror (EINVAL));
+      return 1;
+    }
+
+  return 0;
+#endif
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel-self-canceltype.c b/sysdeps/pthread/tst-cancel-self-canceltype.c
new file mode 100644
index 0000000000..4f4ae08682
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel-self-canceltype.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2012-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+  int ret = 0, should_fail = 0;
+
+  pthread_cleanup_push (cleanup, &should_fail);
+
+  if ((ret = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0)
+    {
+      printf ("setcanceltype failed: %s\n", strerror (ret));
+      exit (1);
+    }
+
+  if ((ret = pthread_cancel (pthread_self ())) != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (ret));
+      exit (1);
+    }
+
+  /* Wait to be canceled. Don't give any cancellation points to play with.  */
+  while (1);
+  pthread_cleanup_pop (0);
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel-self-cleanup.c b/sysdeps/pthread/tst-cancel-self-cleanup.c
new file mode 100644
index 0000000000..5373397f69
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel-self-cleanup.c
@@ -0,0 +1,23 @@
+/* Copyright (C) 2012-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+static void
+cleanup (void *cleanup_should_fail)
+{
+  printf ("Main thread got cancelled and is being cleaned up now\n");
+  exit (*(int *)cleanup_should_fail);
+}
diff --git a/sysdeps/pthread/tst-cancel-self-testcancel.c b/sysdeps/pthread/tst-cancel-self-testcancel.c
new file mode 100644
index 0000000000..f9e4b82137
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel-self-testcancel.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2012-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tst-cancel-self-cleanup.c"
+
+
+static int
+do_test (void)
+{
+  int ret = 0, should_fail = 0;
+
+  pthread_cleanup_push (cleanup, &should_fail);
+  if ((ret = pthread_cancel (pthread_self ())) != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (ret));
+      exit (1);
+    }
+
+  pthread_testcancel ();
+
+  printf ("Could not cancel self.\n");
+  pthread_cleanup_pop (0);
+
+  return 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel1.c b/sysdeps/pthread/tst-cancel1.c
new file mode 100644
index 0000000000..19a12a0b96
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel1.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+  if (arg != (void *) 42l)
+    cntr = 42;
+  else
+    cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  /* Ignore all signals.  This must not have any effect on delivering
+     the cancellation signal.  */
+  sigset_t ss;
+
+  sigfillset (&ss);
+
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("pthread_sigmask failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cleanup, (void *) 42l);
+
+  int err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+  if (err != 0)
+    {
+      printf ("setcanceltype failed: %s\n", strerror (err));
+      exit (1);
+    }
+  /* The following code is not standard compliant: the mutex functions
+     must not be called with asynchronous cancellation enabled.  */
+
+  err = pthread_mutex_unlock (&m2);
+  if (err != 0)
+    {
+      printf ("child: mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int err;
+  pthread_t th;
+  int result = 0;
+  void *retval;
+
+  /* Get the mutexes.  */
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_cancel (th);
+  if (err != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_join (th, &retval);
+  if (err != 0)
+    {
+      printf ("join failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (retval != PTHREAD_CANCELED)
+    {
+      printf ("wrong return value: %p\n", retval);
+      result = 1;
+    }
+
+  if (cntr == 42)
+    {
+      puts ("cleanup handler called with wrong argument");
+      result = 1;
+    }
+  else if (cntr != 1)
+    {
+      puts ("cleanup handling not called");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel10.c b/sysdeps/pthread/tst-cancel10.c
new file mode 100644
index 0000000000..79caefb31f
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel10.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static void
+cleanup (void *arg)
+{
+  /* Just for fun.  */
+  if (pthread_cancel (pthread_self ()) != 0)
+    {
+      puts ("cleanup: cancel failed");
+      exit (1);
+    }
+
+  printf ("cleanup for %ld\n", (long int) arg);
+}
+
+
+static void *
+tf (void *arg)
+{
+  long int n = (long int) arg;
+
+  pthread_cleanup_push (cleanup, arg);
+
+  if (pthread_setcanceltype ((n & 1) == 0
+			     ? PTHREAD_CANCEL_DEFERRED
+			     : PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
+    {
+      puts ("setcanceltype failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (pthread_self ()) != 0)
+    {
+      puts ("cancel failed");
+      exit (1);
+    }
+
+  pthread_testcancel ();
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  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;
+    }
+
+#define N 20
+  int i;
+  pthread_t th[N];
+
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+      {
+	puts ("create failed");
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      void *r;
+      if (pthread_join (th[i], &r) != 0)
+	{
+	  puts ("join failed");
+	  exit (1);
+	}
+
+      if (r != PTHREAD_CANCELED)
+	{
+	  puts ("thread not canceled");
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel12.c b/sysdeps/pthread/tst-cancel12.c
new file mode 100644
index 0000000000..55045f55d2
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel12.c
@@ -0,0 +1,123 @@
+/* Test sem_wait cancellation for uncontended case.
+   Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("error: tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* This call should be cancelable.  */
+  sem_wait (&sem);
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("error: barrier_init failed");
+      exit (1);
+    }
+
+  /* A value higher than 0 will check for uncontended pthread cancellation,
+     where the sem_wait operation will return immediatelly.  */
+  if (sem_init (&sem, 0, 1) != 0)
+    {
+      puts ("error: sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("error: create failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("error: pthread_cancel failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("error: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("error: pthread_join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("error: thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel14.c b/sysdeps/pthread/tst-cancel14.c
new file mode 100644
index 0000000000..32e03eb173
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel14.c
@@ -0,0 +1,133 @@
+/* Test sem_timedwait cancellation for uncontended case.
+   Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("error: tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* Timeout in 5 seconds.  */
+  ts.tv_sec += 5;
+
+  /* This call should block and be cancelable.  */
+  sem_timedwait (&sem, &ts);
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("error: barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 1) != 0)
+    {
+      puts ("error: sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("error: create failed");
+      exit (1);
+    }
+
+  /* Check whether cancellation is honored even before sem_timedwait does
+     anything.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("error: 1st cancel failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel15.c b/sysdeps/pthread/tst-cancel15.c
new file mode 100644
index 0000000000..c16d9d17eb
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel15.c
@@ -0,0 +1,138 @@
+/* Test sem_timedwait cancellation for contended case.
+   Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  int e;
+
+  pthread_cleanup_push (cleanup, NULL);
+
+  e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("error: tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* Timeout in 5 seconds.  */
+  ts.tv_sec += 5;
+
+  /* This call should block and be cancelable.  */
+  errno = 0;
+  e = sem_timedwait (&sem, &ts);
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("error: barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 0) != 0)
+    {
+      puts ("error: sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("error: create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("error: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* Give the child a chance to go to sleep in sem_wait.  */
+  sleep (1);
+
+  /* Check whether cancellation is honored when waiting in sem_timedwait.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("error: 1st cancel failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("error: join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("error: thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel18.c b/sysdeps/pthread/tst-cancel18.c
new file mode 100644
index 0000000000..7dce66c91c
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel18.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t b;
+
+
+/* Cleanup handling test.  */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+  TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
+
+  pthread_cleanup_pop (0);
+
+  puts ("clock_nanosleep returned");
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  while (nanosleep (&ts, &ts) != 0)
+    continue;
+
+  puts ("going to cancel in-time");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      return 1;
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("1st join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("1st thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      puts ("cleanup handler not called");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      puts ("cleanup handler called more than once");
+      return 1;
+    }
+
+  puts ("in-time cancellation succeeded");
+
+
+  cl_called = 0;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("2nd create failed");
+      return 1;
+    }
+
+  puts ("going to cancel early");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("2nd cancel failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("2nd join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      printf ("cleanup handler not called\n");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      printf ("cleanup handler called more than once\n");
+      return 1;
+    }
+
+  puts ("early cancellation succeeded");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel19.c b/sysdeps/pthread/tst-cancel19.c
new file mode 100644
index 0000000000..b6752d8252
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel19.c
@@ -0,0 +1,285 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+static void *
+tf (void *arg)
+{
+  return NULL;
+}
+
+static void
+handler (int sig)
+{
+}
+
+static void __attribute__ ((noinline))
+clobber_lots_of_regs (void)
+{
+#define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
+#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
+#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#define X1(n) __asm __volatile ("" : : "r" (r##n));
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#undef X2
+#undef X3
+}
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int old, rc;
+  int ret = 0;
+  int fd[2];
+
+  rc = pipe (fd);
+  if (rc < 0)
+    error (EXIT_FAILURE, errno, "couldn't create pipe");
+
+  rc = pthread_create (&th, NULL, tf, NULL);
+  if (rc)
+    error (EXIT_FAILURE, rc, "couldn't create thread");
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "1st pthread_setcanceltype failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[0]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[1]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGALRM, &sa, NULL);
+
+  struct itimerval it;
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
+  char *enddir = strchr (fname, '\0');
+  if (mkdtemp (fname) == NULL)
+    {
+      error (0, errno, "mkdtemp failed");
+      ret = 1;
+    }
+  *enddir = '/';
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  *enddir = '\0';
+  rmdir (fname);
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  pthread_join (th, NULL);
+
+  return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel2.c b/sysdeps/pthread/tst-cancel2.c
new file mode 100644
index 0000000000..1e86711596
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel2.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  /* The buffer size must be larger than the pipe size so that the
+     write blocks.  */
+  char buf[100000];
+
+  while (write (fd[1], buf, sizeof (buf)) > 0);
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the write in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel22.c b/sysdeps/pthread/tst-cancel22.c
new file mode 100644
index 0000000000..82a5454132
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel22.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+pthread_barrier_t b;
+int seen;
+
+static void *
+tf (void *arg)
+{
+  int old;
+  int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
+  if (r != 0)
+    {
+      puts ("setcancelstate failed");
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  for (int i = 0; i < 10; ++i)
+    {
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+    }
+
+  seen = 1;
+  pthread_setcancelstate (old, NULL);
+
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+   {
+     puts ("barrier init failed");
+     return 1;
+   }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("thread creation failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 1;
+    }
+
+  if (seen != 1)
+    {
+      puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel23.c b/sysdeps/pthread/tst-cancel23.c
new file mode 100644
index 0000000000..211168748e
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel23.c
@@ -0,0 +1 @@
+#include "tst-cancel22.c"
diff --git a/sysdeps/pthread/tst-cancel26.c b/sysdeps/pthread/tst-cancel26.c
new file mode 100644
index 0000000000..91948ae909
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel26.c
@@ -0,0 +1,68 @@
+/* Check for failure paths handling for cancellation points.
+   Copyright (C) 2015-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Check that the cancel syscall points handles both the errno and return code
+   correctly for invalid arguments.  */
+static void *
+tf (void *arg)
+{
+#ifdef SET_CANCEL_DISABLE
+  pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
+#endif
+
+  /* This is a cancellation point, but we should not be cancelled.  */
+  int r = write (-1, 0, 0);
+
+  if (r != -1 || errno != EBADF)
+    {
+      printf ("error: write returned %d, errno %d\n", r, errno);
+      exit (1);
+    }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("error: pthread_create failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("error: pthread_join failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel27.c b/sysdeps/pthread/tst-cancel27.c
new file mode 100644
index 0000000000..d3d582e22c
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel27.c
@@ -0,0 +1,23 @@
+/* Check for failure paths handling for cancellation points.
+   Copyright (C) 2015-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Similar to tst-cancel26.c but with pthread cancel state set to
+   PTHREAD_CANCEL_DISABLE.  */
+
+#define SET_CANCEL_DISABLE 1
+#include "tst-cancel26.c"
diff --git a/sysdeps/pthread/tst-cancel28.c b/sysdeps/pthread/tst-cancel28.c
new file mode 100644
index 0000000000..11beb0168c
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel28.c
@@ -0,0 +1,79 @@
+/* Check if the thread created by POSIX timer using SIGEV_THREAD is
+   cancellable.
+   Copyright (C) 2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <time.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include <support/check.h>
+#include <support/test-driver.h>
+#include <support/xthread.h>
+
+static pthread_barrier_t barrier;
+static pthread_t timer_thread;
+
+static void
+cl (void *arg)
+{
+  xpthread_barrier_wait (&barrier);
+}
+
+static void
+thread_handler (union sigval sv)
+{
+  timer_thread = pthread_self ();
+
+  xpthread_barrier_wait (&barrier);
+
+  pthread_cleanup_push (cl, NULL);
+  while (1)
+    clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 1, 0 }, NULL);
+  pthread_cleanup_pop (0);
+}
+
+static int
+do_test (void)
+{
+  struct sigevent sev = { 0 };
+  sev.sigev_notify = SIGEV_THREAD;
+  sev.sigev_notify_function = &thread_handler;
+
+  timer_t timerid;
+  TEST_COMPARE (timer_create (CLOCK_REALTIME, &sev, &timerid), 0);
+
+  xpthread_barrier_init (&barrier, NULL, 2);
+
+  struct itimerspec trigger = { 0 };
+  trigger.it_value.tv_nsec = 1000000;
+  TEST_COMPARE (timer_settime (timerid, 0, &trigger, NULL), 0);
+
+  xpthread_barrier_wait (&barrier);
+
+  xpthread_cancel (timer_thread);
+
+  xpthread_barrier_init (&barrier, NULL, 2);
+  xpthread_barrier_wait (&barrier);
+
+  return 0;
+}
+
+/* A stall in cancellation is a regression.  */
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-cancel3.c b/sysdeps/pthread/tst-cancel3.c
new file mode 100644
index 0000000000..0a531dbcdb
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel3.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+
+  if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("read succeeded");
+      return (void *) 1l;
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the read in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancel8.c b/sysdeps/pthread/tst-cancel8.c
new file mode 100644
index 0000000000..0ee1e85db3
--- /dev/null
+++ b/sysdeps/pthread/tst-cancel8.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static pthread_barrier_t bar;
+
+static int global;
+
+
+static void
+cleanup (void *arg)
+{
+  global = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  /* Enable cancellation, but defer it.  */
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+    {
+      puts ("setcancelstate failed");
+      exit (1);
+    }
+  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+    {
+      puts ("setcanceltype failed");
+      exit (1);
+    }
+
+  /* Add cleanup handler.  */
+  pthread_cleanup_push (cleanup, NULL);
+
+  /* Synchronize with the main thread.  */
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: first barrier_wait failed");
+      exit (1);
+    }
+
+  /* And again.  Once this is done the main thread should have canceled
+     this thread.  */
+  r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: second barrier_wait failed");
+      exit (1);
+    }
+
+  /* Remove the cleanup handler without executing it.  */
+  pthread_cleanup_pop (0);
+
+  /* Now react on the cancellation.  */
+  pthread_testcancel ();
+
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("first barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("second barrier_wait failed");
+      exit (1);
+    }
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  if (result != PTHREAD_CANCELED)
+    {
+      puts ("thread was not canceled");
+      exit (1);
+    }
+
+  if (global != 0)
+    {
+      puts ("cancellation handler has been called");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cancelx1.c b/sysdeps/pthread/tst-cancelx1.c
new file mode 100644
index 0000000000..594f095592
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx1.c
@@ -0,0 +1 @@
+#include "tst-cancel1.c"
diff --git a/sysdeps/pthread/tst-cancelx10.c b/sysdeps/pthread/tst-cancelx10.c
new file mode 100644
index 0000000000..e5bbb34e62
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx10.c
@@ -0,0 +1 @@
+#include "tst-cancel10.c"
diff --git a/sysdeps/pthread/tst-cancelx12.c b/sysdeps/pthread/tst-cancelx12.c
new file mode 100644
index 0000000000..f90ae61bac
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx12.c
@@ -0,0 +1 @@
+#include "tst-cancel12.c"
diff --git a/sysdeps/pthread/tst-cancelx14.c b/sysdeps/pthread/tst-cancelx14.c
new file mode 100644
index 0000000000..ba4e77584e
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx14.c
@@ -0,0 +1 @@
+#include "tst-cancel14.c"
diff --git a/sysdeps/pthread/tst-cancelx15.c b/sysdeps/pthread/tst-cancelx15.c
new file mode 100644
index 0000000000..005c1f6e3f
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx15.c
@@ -0,0 +1 @@
+#include "tst-cancel15.c"
diff --git a/sysdeps/pthread/tst-cancelx18.c b/sysdeps/pthread/tst-cancelx18.c
new file mode 100644
index 0000000000..56da18f382
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx18.c
@@ -0,0 +1 @@
+#include "tst-cancel18.c"
diff --git a/sysdeps/pthread/tst-cancelx2.c b/sysdeps/pthread/tst-cancelx2.c
new file mode 100644
index 0000000000..95dc8a8575
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx2.c
@@ -0,0 +1 @@
+#include "tst-cancel2.c"
diff --git a/sysdeps/pthread/tst-cancelx3.c b/sysdeps/pthread/tst-cancelx3.c
new file mode 100644
index 0000000000..3937f10b9c
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx3.c
@@ -0,0 +1 @@
+#include "tst-cancel3.c"
diff --git a/sysdeps/pthread/tst-cancelx8.c b/sysdeps/pthread/tst-cancelx8.c
new file mode 100644
index 0000000000..0555c7ceb0
--- /dev/null
+++ b/sysdeps/pthread/tst-cancelx8.c
@@ -0,0 +1 @@
+#include "tst-cancel8.c"
diff --git a/sysdeps/pthread/tst-cleanup0.c b/sysdeps/pthread/tst-cleanup0.c
new file mode 100644
index 0000000000..fd196abb96
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanup0.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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
+endfct (void)
+{
+  /* We force exit right here.  */
+  _exit (global);
+}
+
+
+static int
+do_test (void)
+{
+  atexit (endfct);
+
+  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 100;
+}
+
+
+#define EXPECTED_STATUS 9
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-cleanup0.expect b/sysdeps/pthread/tst-cleanup0.expect
new file mode 100644
index 0000000000..4e3c581802
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanup0.expect
@@ -0,0 +1,3 @@
+ch (3)
+ch (2)
+ch (1)
diff --git a/sysdeps/pthread/tst-cleanup1.c b/sysdeps/pthread/tst-cleanup1.c
new file mode 100644
index 0000000000..7805479857
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanup1.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+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_message ("create failed\n");
+      _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;
+}
diff --git a/sysdeps/pthread/tst-cleanup2.c b/sysdeps/pthread/tst-cleanup2.c
new file mode 100644
index 0000000000..5936c242fc
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanup2.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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;
+  /* gcc can overwrite the success written value by scheduling instructions
+     around sprintf.  It is allowed to do this since according to C99 the first
+     argument of sprintf is a character array and NULL is not a valid character
+     array.  Mark the return value as volatile so that it gets reloaded on
+     return.  */
+  volatile int ret = 0;
+
+  if (signal (SIGSEGV, &sig_handler) == SIG_ERR)
+    {
+      perror ("installing SIGSEGV handler");
+      return 1;
+    }
+
+  puts ("Attempting to sprintf to null ptr");
+  if (setjmp (jmpbuf))
+    {
+      puts ("Exiting main...");
+      return ret;
+    }
+
+  sprintf (p, "This should segv\n");
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cleanup3.c b/sysdeps/pthread/tst-cleanup3.c
new file mode 100644
index 0000000000..150d56162f
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanup3.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+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_message ("create failed\n");
+      _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;
+}
diff --git a/sysdeps/pthread/tst-cleanupx0.c b/sysdeps/pthread/tst-cleanupx0.c
new file mode 100644
index 0000000000..0012ab1b25
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanupx0.c
@@ -0,0 +1 @@
+#include "tst-cleanup0.c"
diff --git a/sysdeps/pthread/tst-cleanupx0.expect b/sysdeps/pthread/tst-cleanupx0.expect
new file mode 100644
index 0000000000..4e3c581802
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanupx0.expect
@@ -0,0 +1,3 @@
+ch (3)
+ch (2)
+ch (1)
diff --git a/sysdeps/pthread/tst-cleanupx1.c b/sysdeps/pthread/tst-cleanupx1.c
new file mode 100644
index 0000000000..21e9e58bd6
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanupx1.c
@@ -0,0 +1 @@
+#include "tst-cleanup1.c"
diff --git a/sysdeps/pthread/tst-cleanupx2.c b/sysdeps/pthread/tst-cleanupx2.c
new file mode 100644
index 0000000000..8b9e350935
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanupx2.c
@@ -0,0 +1 @@
+#include "tst-cleanup2.c"
diff --git a/sysdeps/pthread/tst-cleanupx3.c b/sysdeps/pthread/tst-cleanupx3.c
new file mode 100644
index 0000000000..90baf904f9
--- /dev/null
+++ b/sysdeps/pthread/tst-cleanupx3.c
@@ -0,0 +1 @@
+#include "tst-cleanup3.c"
diff --git a/sysdeps/pthread/tst-clock1.c b/sysdeps/pthread/tst-clock1.c
new file mode 100644
index 0000000000..26ef56852d
--- /dev/null
+++ b/sysdeps/pthread/tst-clock1.c
@@ -0,0 +1,50 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+  clockid_t cl;
+  /* This is really only a linking-test here.  */
+  int e = pthread_getcpuclockid (pthread_self (), &cl);
+  if (e != 0)
+    {
+# if _POSIX_THREAD_CPUTIME == 0
+      if (sysconf (_SC_THREAD_CPUTIME) >= 0)
+# endif
+	{
+	  puts ("cpuclock advertized, but cannot get ID");
+	  exit (1);
+	}
+    }
+#endif
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cond22.c b/sysdeps/pthread/tst-cond22.c
deleted file mode 100644
index 64f19ea0a5..0000000000
--- a/sysdeps/pthread/tst-cond22.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-static pthread_barrier_t b;
-static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
-
-
-static void
-cl (void *arg)
-{
-  pthread_mutex_unlock (&m);
-}
-
-
-static void *
-tf (void *arg)
-{
-  if (pthread_mutex_lock (&m) != 0)
-    {
-      printf ("%s: mutex_lock failed\n", __func__);
-      exit (1);
-    }
-  int e = pthread_barrier_wait (&b);
-  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
-    {
-      printf ("%s: barrier_wait failed\n", __func__);
-      exit (1);
-    }
-  pthread_cleanup_push (cl, NULL);
-  /* We have to loop here because the cancellation might come after
-     the cond_wait call left the cancelable area and is then waiting
-     on the mutex.  In this case the beginning of the second cond_wait
-     call will cause the cancellation to happen.  */
-  do
-    if (pthread_cond_wait (&c, &m) != 0)
-      {
-	printf ("%s: cond_wait failed\n", __func__);
-	exit (1);
-      }
-  while (arg == NULL);
-  pthread_cleanup_pop (0);
-  if (pthread_mutex_unlock (&m) != 0)
-    {
-      printf ("%s: mutex_unlock failed\n", __func__);
-      exit (1);
-    }
-  return NULL;
-}
-
-
-static int
-do_test (void)
-{
-  int status = 0;
-
-  if (pthread_barrier_init (&b, NULL, 2) != 0)
-    {
-      puts ("barrier_init failed");
-      return 1;
-    }
-
-  pthread_t th;
-  if (pthread_create (&th, NULL, tf, NULL) != 0)
-    {
-      puts ("1st create failed");
-      return 1;
-    }
-  int e = pthread_barrier_wait (&b);
-  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
-    {
-      puts ("1st barrier_wait failed");
-      return 1;
-    }
-  if (pthread_mutex_lock (&m) != 0)
-    {
-      puts ("1st mutex_lock failed");
-      return 1;
-    }
-  if (pthread_cond_signal (&c) != 0)
-    {
-      puts ("1st cond_signal failed");
-      return 1;
-    }
-  if (pthread_cancel (th) != 0)
-    {
-      puts ("cancel failed");
-      return 1;
-    }
-  if (pthread_mutex_unlock (&m) != 0)
-    {
-      puts ("1st mutex_unlock failed");
-      return 1;
-    }
-  void *res;
-  if (pthread_join (th, &res) != 0)
-    {
-      puts ("1st join failed");
-      return 1;
-    }
-  if (res != PTHREAD_CANCELED)
-    {
-      puts ("first thread not canceled");
-      status = 1;
-    }
-
-  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
-	  c.__data.__wseq, c.__data.__g1_start,
-	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
-	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
-	  c.__data.__g1_orig_size, c.__data.__wrefs);
-
-  if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
-    {
-      puts ("2nd create failed");
-      return 1;
-    }
-  e = pthread_barrier_wait (&b);
-  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
-    {
-      puts ("2nd barrier_wait failed");
-      return 1;
-    }
-  if (pthread_mutex_lock (&m) != 0)
-    {
-      puts ("2nd mutex_lock failed");
-      return 1;
-    }
-  if (pthread_cond_signal (&c) != 0)
-    {
-      puts ("2nd cond_signal failed");
-      return 1;
-    }
-  if (pthread_mutex_unlock (&m) != 0)
-    {
-      puts ("2nd mutex_unlock failed");
-      return 1;
-    }
-  if (pthread_join (th, &res) != 0)
-    {
-      puts ("2nd join failed");
-      return 1;
-    }
-  if (res != NULL)
-    {
-      puts ("2nd thread canceled");
-      status = 1;
-    }
-
-  printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
-	  c.__data.__wseq, c.__data.__g1_start,
-	  c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
-	  c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
-	  c.__data.__g1_orig_size, c.__data.__wrefs);
-
-  return status;
-}
-
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-cond26.c b/sysdeps/pthread/tst-cond26.c
deleted file mode 100644
index e647da00c2..0000000000
--- a/sysdeps/pthread/tst-cond26.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
-
-   Copyright (C) 2019-2020 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, see
-   <https://www.gnu.org/licenses/>.  */
-
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <time.h>
-#include <unistd.h>
-#include <support/check.h>
-#include <support/timespec.h>
-#include <support/xthread.h>
-
-static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
-#define NOT_A_VALID_CLOCK 123456
-
-static int
-do_test (void)
-{
-  xpthread_mutex_lock (&mut);
-
-  const struct timespec ts = make_timespec (0, 0);
-
-  /* These clocks are meaningless to sem_clockwait.  */
-#if defined(CLOCK_PROCESS_CPUTIME_ID)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
-#endif
-#if defined(CLOCK_THREAD_CPUTIME_ID)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
-#endif
-
-  /* These clocks might be meaningful, but are currently unsupported
-     by pthread_cond_clockwait.  */
-#if defined(CLOCK_REALTIME_COARSE)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_REALTIME_COARSE, &ts), EINVAL);
-#endif
-#if defined(CLOCK_MONOTONIC_RAW)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_MONOTONIC_RAW, &ts), EINVAL);
-#endif
-#if defined(CLOCK_MONOTONIC_COARSE)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
-#endif
-#if defined(CLOCK_BOOTTIME)
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        CLOCK_BOOTTIME, &ts), EINVAL);
-#endif
-
-  /* This is a completely invalid clock.  */
-  TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
-                                        NOT_A_VALID_CLOCK, &ts), EINVAL);
-
-  return 0;
-}
-
-#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-create-detached.c b/sysdeps/pthread/tst-create-detached.c
new file mode 100644
index 0000000000..cd79c68908
--- /dev/null
+++ b/sysdeps/pthread/tst-create-detached.c
@@ -0,0 +1,138 @@
+/* Bug 20116: Test rapid creation of detached threads.
+   Copyright (C) 2017-2020 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; see the file COPYING.LIB.  If
+   not, see <https://www.gnu.org/licenses/>.  */
+
+/* The goal of the test is to trigger a failure if the parent touches
+   any part of the thread descriptor after the detached thread has
+   exited.  We test this by creating many detached threads with large
+   stacks.  The stacks quickly fill the the stack cache and subsequent
+   threads will start to cause the thread stacks to be immediately
+   unmapped to satisfy the stack cache max.  With the stacks being
+   unmapped the parent's read of any part of the thread descriptor will
+   trigger a segfault.  That segfault is what we are trying to cause,
+   since any segfault is a defect in the implementation.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <support/xthread.h>
+
+/* Number of threads to create.  */
+enum { threads_to_create = 100000 };
+
+/* Number of threads which should spawn other threads.  */
+enum { creator_threads  = 2 };
+
+/* Counter of threads created so far.  This is incremented by all the
+   running creator threads.  */
+static unsigned threads_created;
+
+/* Thread callback which does nothing, so that the thread exits
+   immediatedly.  */
+static void *
+do_nothing (void *arg)
+{
+  return NULL;
+}
+
+/* Attribute indicating that the thread should be created in a detached
+   fashion.  */
+static pthread_attr_t detached;
+
+/* Barrier to synchronize initialization.  */
+static pthread_barrier_t barrier;
+
+static void *
+creator_thread (void *arg)
+{
+  int ret;
+  xpthread_barrier_wait (&barrier);
+
+  while (true)
+    {
+      pthread_t thr;
+      /* Thread creation will fail if the kernel does not free old
+	 threads quickly enough, so we do not report errors.  */
+      ret = pthread_create (&thr, &detached, do_nothing, NULL);
+      if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
+          >= threads_to_create)
+        break;
+    }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  /* Limit the size of the process, so that memory allocation will
+     fail without impacting the entire system.  */
+  {
+    struct rlimit limit;
+    if (getrlimit (RLIMIT_AS, &limit) != 0)
+      {
+        printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
+        return 1;
+      }
+    /* This limit, 800MB, is just a heuristic. Any value can be
+       picked.  */
+    long target = 800 * 1024 * 1024;
+    if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
+      {
+        limit.rlim_cur = target;
+        if (setrlimit (RLIMIT_AS, &limit) != 0)
+          {
+            printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
+            return 1;
+          }
+      }
+  }
+
+  xpthread_attr_init (&detached);
+
+  xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);
+
+  /* A large thread stack seems beneficial for reproducing a race
+     condition in detached thread creation.  The goal is to reach the
+     limit of the runtime thread stack cache such that the detached
+     thread's stack is unmapped after exit and causes a segfault when
+     the parent reads the thread descriptor data stored on the the
+     unmapped stack.  */
+  xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);
+
+  xpthread_barrier_init (&barrier, NULL, creator_threads);
+
+  pthread_t threads[creator_threads];
+
+  for (int i = 0; i < creator_threads; ++i)
+    threads[i] = xpthread_create (NULL, creator_thread, NULL);
+
+  for (int i = 0; i < creator_threads; ++i)
+    xpthread_join (threads[i]);
+
+  xpthread_attr_destroy (&detached);
+
+  xpthread_barrier_destroy (&barrier);
+
+  return 0;
+}
+
+#define TIMEOUT 100
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-detach1.c b/sysdeps/pthread/tst-detach1.c
new file mode 100644
index 0000000000..b45732d3c1
--- /dev/null
+++ b/sysdeps/pthread/tst-detach1.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-eintr2.c b/sysdeps/pthread/tst-eintr2.c
new file mode 100644
index 0000000000..4f26ccad04
--- /dev/null
+++ b/sysdeps/pthread/tst-eintr2.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <support/check.h>
+#include <support/timespec.h>
+#include <support/xtime.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 = timespec_add (xclock_now (CLOCK_REALTIME),
+                                     make_timespec (10000, 0));
+
+  /* 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)
+    {
+      TEST_COMPARE (pthread_mutex_lock (&m2), 0);
+      TEST_COMPARE (pthread_mutex_unlock (&m2), 0);
+
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+      nanosleep (&ts, NULL);
+    }
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  TEST_COMPARE (pthread_mutex_lock (&m1), 0);
+
+  setup_eintr (SIGUSR1, NULL);
+
+  char buf[100];
+  xpthread_create (NULL, tf1, NULL);
+  xpthread_create (NULL, tf2, NULL);
+
+  delayed_exit (3);
+  /* This call must never return.  */
+  int e = pthread_mutex_lock (&m1);
+  printf ("main: mutex_lock returned: %s\n",
+	  strerror_r (e, buf, sizeof (buf)));
+
+  return 1;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-eintr3.c b/sysdeps/pthread/tst-eintr3.c
new file mode 100644
index 0000000000..528ead1fc4
--- /dev/null
+++ b/sysdeps/pthread/tst-eintr3.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+#include "eintr.c"
+
+
+static void *
+tf (void *arg)
+{
+  pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+  xpthread_mutex_lock (&m);
+  /* This call must not return.  */
+  xpthread_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 = xpthread_create (NULL, tf, NULL);
+
+  delayed_exit (1);
+  /* This call must never return.  */
+  xpthread_join (th);
+  puts ("error: pthread_join returned");
+  return 1;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-eintr4.c b/sysdeps/pthread/tst-eintr4.c
new file mode 100644
index 0000000000..14f3675519
--- /dev/null
+++ b/sysdeps/pthread/tst-eintr4.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+#include "eintr.c"
+
+
+static int
+do_test (void)
+{
+  pthread_t self = pthread_self ();
+
+  setup_eintr (SIGUSR1, &self);
+
+  pthread_barrier_t b;
+  xpthread_barrier_init (&b, NULL, 2);
+
+  delayed_exit (1);
+  /* This call must never return.  */
+  xpthread_barrier_wait (&b);
+  puts ("error: pthread_barrier_wait returned");
+  return 1;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-eintr5.c b/sysdeps/pthread/tst-eintr5.c
new file mode 100644
index 0000000000..bc6c0fef53
--- /dev/null
+++ b/sysdeps/pthread/tst-eintr5.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <support/check.h>
+#include <support/timespec.h>
+#include <support/xthread.h>
+#include <support/xtime.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 = timespec_add (xclock_now (CLOCK_REALTIME),
+                                     make_timespec (10000, 0));
+
+  /* This call must never return.  */
+  TEST_COMPARE (pthread_cond_timedwait (&c, &m, &ts), 0);
+  FAIL_EXIT1 ("pthread_cond_timedwait returned unexpectedly\n");
+}
+
+
+static int
+do_test (void)
+{
+  setup_eintr (SIGUSR1, NULL);
+
+  xpthread_create (NULL, tf, NULL);
+
+  delayed_exit (3);
+  /* This call must never return.  */
+  xpthread_cond_wait (&c, &m);
+  FAIL_RET ("error: pthread_cond_wait returned");
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-exec1.c b/sysdeps/pthread/tst-exec1.c
new file mode 100644
index 0000000000..892107d4c7
--- /dev/null
+++ b/sysdeps/pthread/tst-exec1.c
@@ -0,0 +1,156 @@
+/* Simple exec test, only a thread in the parent.
+   Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <support/xsignal.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.  */
+  xsignal (SIGPIPE, SIG_IGN);
+
+  posix_spawn_file_actions_t a;
+  if (posix_spawn_file_actions_init (&a) != 0)
+    {
+      puts ("spawn_file_actions_init failed");
+      exit (1);
+    }
+
+  if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
+    {
+      puts ("spawn_file_actions_adddup2 failed");
+      exit (1);
+    }
+
+  if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
+    {
+      puts ("spawn_file_actions_addclose");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  pid_t pid;
+  char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
+		   NULL };
+  if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
+    {
+      puts ("spawn 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);
+    }
+
+  puts ("read correct PID");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-exec2.c b/sysdeps/pthread/tst-exec2.c
new file mode 100644
index 0000000000..f57903da1e
--- /dev/null
+++ b/sysdeps/pthread/tst-exec2.c
@@ -0,0 +1,151 @@
+/* Thread with running thread calls exec.
+   Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <support/xsignal.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.  */
+  xsignal (SIGPIPE, SIG_IGN);
+
+  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/sysdeps/pthread/tst-exec3.c b/sysdeps/pthread/tst-exec3.c
new file mode 100644
index 0000000000..b849d3aef7
--- /dev/null
+++ b/sysdeps/pthread/tst-exec3.c
@@ -0,0 +1,149 @@
+/* Thread calls exec.
+   Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <paths.h>
+#include <pthread.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <support/xsignal.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.  */
+  xsignal (SIGPIPE, SIG_IGN);
+
+  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/sysdeps/pthread/tst-exit1.c b/sysdeps/pthread/tst-exit1.c
new file mode 100644
index 0000000000..4ecc3d4ac5
--- /dev/null
+++ b/sysdeps/pthread/tst-exit1.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
+   exit to be called more than once.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  /* Do nothing.  */
+  if (pthread_join (th, NULL) == 0)
+    {
+      puts ("join succeeded!?");
+      exit (1);
+    }
+
+  puts ("join returned!?");
+  exit (1);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-exit2.c b/sysdeps/pthread/tst-exit2.c
new file mode 100644
index 0000000000..0b7a2caf6a
--- /dev/null
+++ b/sysdeps/pthread/tst-exit2.c
@@ -0,0 +1,42 @@
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void *
+tf (void *arg)
+{
+  while (1)
+    sleep (100);
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      return 1;
+    }
+
+  delayed_exit (1);
+
+  /* Terminate only this thread.  */
+  pthread_exit (NULL);
+
+  /* NOTREACHED */
+  return 1;
+}
diff --git a/sysdeps/pthread/tst-exit3.c b/sysdeps/pthread/tst-exit3.c
new file mode 100644
index 0000000000..9481ed9b42
--- /dev/null
+++ b/sysdeps/pthread/tst-exit3.c
@@ -0,0 +1,83 @@
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static pthread_barrier_t b;
+
+
+static void *
+tf2 (void *arg)
+{
+  while (1)
+    sleep (100);
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_t th;
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_create (&th, NULL, tf2, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      exit (1);
+    }
+
+  /* Terminate only this thread.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  delayed_exit (3);
+
+  /* Terminate only this thread.  */
+  pthread_exit (NULL);
+
+  /* NOTREACHED */
+  return 1;
+}
diff --git a/sysdeps/pthread/tst-flock1.c b/sysdeps/pthread/tst-flock1.c
new file mode 100644
index 0000000000..65faf46150
--- /dev/null
+++ b/sysdeps/pthread/tst-flock1.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-fork1.c b/sysdeps/pthread/tst-fork1.c
new file mode 100644
index 0000000000..fe5e015a2a
--- /dev/null
+++ b/sysdeps/pthread/tst-fork1.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath <roland@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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+static void *
+thread_function (void * arg)
+{
+  int i = (intptr_t) arg;
+  int status;
+  pid_t pid;
+  pid_t pid2;
+
+  pid = fork ();
+  switch (pid)
+    {
+    case 0:
+      printf ("%ld for %d\n", (long int) getpid (), i);
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 * i };
+      nanosleep (&ts, NULL);
+      _exit (i);
+      break;
+    case -1:
+      printf ("fork: %m\n");
+      return (void *) 1l;
+      break;
+    }
+
+  pid2 = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+  if (pid2 != pid)
+    {
+      printf ("waitpid returned %ld, expected %ld\n",
+	      (long int) pid2, (long int) pid);
+      return (void *) 1l;
+    }
+
+  printf ("%ld with %d, expected %d\n",
+	  (long int) pid, WEXITSTATUS (status), i);
+
+  return WEXITSTATUS (status) == i ? NULL : (void *) 1l;
+}
+
+#define N 5
+static const int t[N] = { 7, 6, 5, 4, 3 };
+
+static int
+do_test (void)
+{
+  pthread_t th[N];
+  int i;
+  int result = 0;
+  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)
+    if (pthread_create (&th[i], NULL, thread_function,
+			(void *) (intptr_t) t[i]) != 0)
+      {
+	printf ("creation of thread %d failed\n", i);
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      void *v;
+      if (pthread_join (th[i], &v) != 0)
+	{
+	  printf ("join of thread %d failed\n", i);
+	  result = 1;
+	}
+      else if (v != NULL)
+	{
+	  printf ("join %d successful, but child failed\n", i);
+	  result = 1;
+	}
+      else
+	printf ("join %d successful\n", i);
+    }
+
+  return result;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-fork2.c b/sysdeps/pthread/tst-fork2.c
new file mode 100644
index 0000000000..bfebab3c92
--- /dev/null
+++ b/sysdeps/pthread/tst-fork2.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath <roland@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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf (void *arg)
+{
+  if (getppid () != initial_pid)
+    {
+      printf ("getppid in thread returned %ld, expected %ld\n",
+	      (long int) getppid (), (long int) initial_pid);
+      return (void *) -1;
+    }
+
+  return NULL;
+}
+
+
+int
+main (void)
+{
+  initial_pid = getpid ();
+
+  pid_t child = fork ();
+  if (child == 0)
+    {
+      if (getppid () != initial_pid)
+	{
+	  printf ("first getppid returned %ld, expected %ld\n",
+		  (long int) getppid (), (long int) initial_pid);
+	  exit (1);
+	}
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("pthread_create failed");
+	  exit (1);
+	}
+
+      void *result;
+      if (pthread_join (th, &result) != 0)
+	{
+	  puts ("pthread_join failed");
+	  exit  (1);
+	}
+
+      exit (result == NULL ? 0 : 1);
+    }
+  else if (child == -1)
+    {
+      puts ("initial fork failed");
+      return 1;
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      printf ("waitpid failed: %m\n");
+      return 1;
+    }
+
+  return status;
+}
diff --git a/sysdeps/pthread/tst-fork3.c b/sysdeps/pthread/tst-fork3.c
new file mode 100644
index 0000000000..2da4c39698
--- /dev/null
+++ b/sysdeps/pthread/tst-fork3.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath <roland@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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf2 (void *arg)
+{
+  if (getppid () != initial_pid)
+    {
+      printf ("getppid in thread returned %ld, expected %ld\n",
+	      (long int) getppid (), (long int) initial_pid);
+      return (void *) -1;
+    }
+
+  return NULL;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+  pid_t child = fork ();
+  if (child == 0)
+    {
+      if (getppid () != initial_pid)
+	{
+	  printf ("first getppid returned %ld, expected %ld\n",
+		  (long int) getppid (), (long int) initial_pid);
+	  exit (1);
+	}
+
+      pthread_t th2;
+      if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+	{
+	  puts ("child: pthread_create failed");
+	  exit (1);
+	}
+
+      void *result;
+      if (pthread_join (th2, &result) != 0)
+	{
+	  puts ("pthread_join failed");
+	  exit  (1);
+	}
+
+      exit (result == NULL ? 0 : 1);
+    }
+  else if (child == -1)
+    {
+      puts ("initial fork failed");
+      exit (1);
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      printf ("waitpid failed: %m\n");
+      exit (1);
+    }
+
+  exit (status);
+}
+
+
+static int
+do_test (void)
+{
+  initial_pid = getpid ();
+
+  pthread_t th1;
+  if (pthread_create (&th1, NULL, tf1, NULL) != 0)
+    {
+      puts ("parent: pthread_create failed");
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_join (th1, NULL);
+
+  return 1;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-fork4.c b/sysdeps/pthread/tst-fork4.c
new file mode 100644
index 0000000000..3efbb724f8
--- /dev/null
+++ b/sysdeps/pthread/tst-fork4.c
@@ -0,0 +1,64 @@
+/* Test of fork updating child universe's pthread structures.
+   Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+  pthread_t me = pthread_self ();
+
+  pid_t pid = fork ();
+
+  if (pid < 0)
+    {
+      printf ("fork: %m\n");
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      int err = pthread_kill (me, SIGTERM);
+      printf ("pthread_kill returned: %s\n", strerror (err));
+      return 3;
+    }
+
+  int status;
+  errno = 0;
+  if (wait (&status) != pid)
+    printf ("wait failed: %m\n");
+  else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM)
+    {
+      printf ("child correctly died with SIGTERM\n");
+      return 0;
+    }
+  else
+    printf ("child died with bad status %#x\n", status);
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-getpid3.c b/sysdeps/pthread/tst-getpid3.c
new file mode 100644
index 0000000000..f1e77f6b10
--- /dev/null
+++ b/sysdeps/pthread/tst-getpid3.c
@@ -0,0 +1,114 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static pid_t pid;
+
+static void *
+pid_thread (void *arg)
+{
+  if (pid != getpid ())
+    {
+      printf ("pid wrong in thread: should be %d, is %d\n",
+	      (int) pid, (int) getpid ());
+      return (void *) 1L;
+    }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pid = getpid ();
+
+  pthread_t thr;
+  int ret = pthread_create (&thr, NULL, pid_thread, NULL);
+  if (ret)
+    {
+      printf ("pthread_create failed: %d\n", ret);
+      return 1;
+    }
+
+  void *thr_ret;
+  ret = pthread_join (thr, &thr_ret);
+  if (ret)
+    {
+      printf ("pthread_create failed: %d\n", ret);
+      return 1;
+    }
+  else if (thr_ret)
+    {
+      printf ("thread getpid failed\n");
+      return 1;
+    }
+
+  pid_t child = fork ();
+  if (child == -1)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+  else if (child == 0)
+    {
+      if (pid == getpid ())
+	{
+	  puts ("pid did not change after fork");
+	  exit (1);
+	}
+
+      pid = getpid ();
+      ret = pthread_create (&thr, NULL, pid_thread, NULL);
+      if (ret)
+	{
+	  printf ("pthread_create failed: %d\n", ret);
+	  return 1;
+	}
+
+      ret = pthread_join (thr, &thr_ret);
+      if (ret)
+	{
+	  printf ("pthread_create failed: %d\n", ret);
+	  return 1;
+	}
+      else if (thr_ret)
+	{
+	  printf ("thread getpid failed\n");
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      puts ("waitpid failed");
+      kill (child, SIGKILL);
+      return 1;
+    }
+
+  if (!WIFEXITED (status))
+    {
+      if (WIFSIGNALED (status))
+	printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
+      else
+	puts ("did not terminate correctly");
+      return 1;
+    }
+  if (WEXITSTATUS (status) != 0)
+    {
+      printf ("exit code %d\n", WEXITSTATUS (status));
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-kill1.c b/sysdeps/pthread/tst-kill1.c
new file mode 100644
index 0000000000..f49598cc83
--- /dev/null
+++ b/sysdeps/pthread/tst-kill1.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-kill2.c b/sysdeps/pthread/tst-kill2.c
new file mode 100644
index 0000000000..a91cf33b44
--- /dev/null
+++ b/sysdeps/pthread/tst-kill2.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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 TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-kill3.c b/sysdeps/pthread/tst-kill3.c
new file mode 100644
index 0000000000..f2dec0a305
--- /dev/null
+++ b/sysdeps/pthread/tst-kill3.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+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_message ("handler called\n");
+  _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;
+}
diff --git a/sysdeps/pthread/tst-kill4.c b/sysdeps/pthread/tst-kill4.c
new file mode 100644
index 0000000000..916ea14820
--- /dev/null
+++ b/sysdeps/pthread/tst-kill4.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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_attr_t at;
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_create failed");
+      exit (1);
+    }
+
+  /* Limit thread stack size, because if it is too large, pthread_join
+     will free it immediately rather than put it into stack cache.  */
+  if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0)
+    {
+      puts ("setstacksize failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, &at, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  pthread_attr_destroy (&at);
+
+  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 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/sysdeps/pthread/tst-kill5.c b/sysdeps/pthread/tst-kill5.c
new file mode 100644
index 0000000000..aefe3d6604
--- /dev/null
+++ b/sysdeps/pthread/tst-kill5.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.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 (), INT_MAX);
+  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/sysdeps/pthread/tst-kill6.c b/sysdeps/pthread/tst-kill6.c
new file mode 100644
index 0000000000..eaec47ccdb
--- /dev/null
+++ b/sysdeps/pthread/tst-kill6.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static pthread_t receiver;
+static sem_t sem;
+static pthread_barrier_t b;
+
+static void
+handler (int sig)
+{
+  if (sig != SIGUSR1)
+    {
+      write_message ("wrong signal\n");
+      _exit (1);
+    }
+
+  if (pthread_self () != receiver)
+    {
+      write_message ("not the intended receiver\n");
+      _exit (1);
+    }
+
+  if (sem_post (&sem) != 0)
+    {
+      write_message ("sem_post failed\n");
+      _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;
+}
diff --git a/sysdeps/pthread/tst-locale1.c b/sysdeps/pthread/tst-locale1.c
new file mode 100644
index 0000000000..887b9a6dd7
--- /dev/null
+++ b/sysdeps/pthread/tst-locale1.c
@@ -0,0 +1,22 @@
+/* Test that the thread-local locale works right in the main thread
+   when statically linked.  */
+
+#include "../locale/tst-C-locale.c"
+
+#include <pthread.h>
+#include <signal.h>
+
+/* This is never called, just here to get pthreads linked in.  */
+int
+useless (void)
+{
+  pthread_t th;
+  pthread_create (&th, 0, (void *(*) (void *)) useless, 0);
+  int result = 0;
+#ifdef SIGRTMIN
+  /* This is to check __libc_current_sigrt* can be used in statically
+     linked apps.  */
+  result = SIGRTMIN;
+#endif
+  return result;
+}
diff --git a/sysdeps/pthread/tst-locale2.c b/sysdeps/pthread/tst-locale2.c
new file mode 100644
index 0000000000..a238209f87
--- /dev/null
+++ b/sysdeps/pthread/tst-locale2.c
@@ -0,0 +1,15 @@
+/* Test that the thread-local locale works right in the main thread
+   when statically linked.  */
+
+#include "../argp/tst-argp1.c"
+
+#include <pthread.h>
+
+/* This is never called, just here to get pthreads linked in.  */
+void *
+useless (void *a)
+{
+  pthread_t th;
+  pthread_create (&th, 0, useless, a);
+  return NULL;
+}
diff --git a/sysdeps/pthread/tst-memstream.c b/sysdeps/pthread/tst-memstream.c
new file mode 100644
index 0000000000..4e8d86cb8b
--- /dev/null
+++ b/sysdeps/pthread/tst-memstream.c
@@ -0,0 +1,101 @@
+/* Test for open_memstream locking.
+   Copyright (C) 2017-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* This test checks if concurrent writes to a FILE created with
+   open_memstream are correctly interleaved without loss or corruption
+   of data.  Large number of concurrent fputc operations are used
+   and in the end the bytes written to the memstream buffer are
+   counted to see if they all got recorded.
+
+   This is a regression test to see if the single threaded stdio
+   optimization broke multi-threaded open_memstream usage.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+enum
+{
+  thread_count = 2,
+  byte_count = 1000000,
+};
+
+struct closure
+{
+  FILE *fp;
+  char b;
+};
+
+static void *
+thread_func (void *closure)
+{
+  struct closure *args = closure;
+
+  for (int i = 0; i < byte_count; ++i)
+    fputc (args->b, args->fp);
+
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  char *buffer = NULL;
+  size_t buffer_length = 0;
+  FILE *fp = open_memstream (&buffer, &buffer_length);
+  if (fp == NULL)
+    FAIL_RET ("open_memstream: %m");
+
+  pthread_t threads[thread_count];
+  struct closure args[thread_count];
+
+  for (int i = 0; i < thread_count; ++i)
+    {
+      args[i].fp = fp;
+      args[i].b = 'A' + i;
+      threads[i] = xpthread_create (NULL, thread_func, args + i);
+    }
+
+  for (int i = 0; i < thread_count; ++i)
+    xpthread_join (threads[i]);
+
+  fclose (fp);
+
+  if (buffer_length != thread_count * byte_count)
+    FAIL_RET ("unexpected number of written bytes: %zu (should be %d)",
+	      buffer_length, thread_count * byte_count);
+
+  /* Verify that each thread written its unique character byte_count times.  */
+  size_t counts[thread_count] = { 0, };
+  for (size_t i = 0; i < buffer_length; ++i)
+    {
+      if (buffer[i] < 'A' || buffer[i] >= 'A' + thread_count)
+	FAIL_RET ("written byte at %zu out of range: %d", i, buffer[i] & 0xFF);
+      ++counts[buffer[i] - 'A'];
+    }
+  for (int i = 0; i < thread_count; ++i)
+    if (counts[i] != byte_count)
+      FAIL_RET ("incorrect write count for thread %d: %zu (should be %d)", i,
+		counts[i], byte_count);
+
+  return 0;
+}
+
+#define TIMEOUT 100
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-pt-align.c b/sysdeps/pthread/tst-pt-align.c
new file mode 100644
index 0000000000..6bb030fc13
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-align.c
@@ -0,0 +1,70 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static void *
+tf (void *arg)
+{
+  bool ok = true;
+
+  puts ("in thread");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? NULL : (void *) -1l;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != NULL)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-pt-align3.c b/sysdeps/pthread/tst-pt-align3.c
new file mode 100644
index 0000000000..b9a35f9586
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-align3.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2005-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static bool ok = true;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static void
+once_test (void)
+{
+  puts ("in once_test");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+}
+
+static int
+do_test (void)
+{
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  if (pthread_once (&once, once_test))
+    {
+      puts ("pthread once failed");
+      return 1;
+    }
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-pt-popen1.c b/sysdeps/pthread/tst-pt-popen1.c
new file mode 100644
index 0000000000..0726447be1
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-popen1.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-pt-sysconf.c b/sysdeps/pthread/tst-pt-sysconf.c
new file mode 100644
index 0000000000..6c5305b420
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-sysconf.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int
+do_test (void)
+{
+  puts ("We expect no limits");
+  /* We have no fixed limit on the number of threads.  Make sure the
+     headers tell the right story.  */
+#ifdef PTHREAD_THREADS_MAX
+  printf ("Header report maximum number of threads = %lu\n",
+	  (unsigned long int) PTHREAD_THREADS_MAX);
+  return 1;
+#else
+  long int r = sysconf (_SC_THREAD_THREADS_MAX);
+  if (r != -1)
+    {
+      printf ("sysconf(_SC_THREAD_THREADS_MAX) return %ld\n", r);
+      return 1;
+    }
+#endif
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-pt-tls1.c b/sysdeps/pthread/tst-pt-tls1.c
new file mode 100644
index 0000000000..727610bc0a
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-tls1.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <support/support.h>
+#include <support/check.h>
+#include <support/xthread.h>
+
+struct test_s
+{
+  __attribute__ ((aligned(0x20))) int a;
+  __attribute__ ((aligned(0x200))) 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
+};
+
+/* Use noinline in combination with not static to ensure that the
+   alignment check is really done.  Otherwise it was optimized out!  */
+__attribute__ ((noinline)) void
+check_alignment (const char *thr_name, const char *ptr_name,
+		 int *ptr, int alignment)
+{
+  uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1);
+  if (offset_aligment)
+    {
+      FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n",
+		  ptr_name, ptr, alignment, thr_name);
+    }
+}
+
+static void
+check_s (const char *thr_name)
+{
+  if (s.a != INIT_A || s.b != INIT_B)
+    FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name);
+
+  check_alignment (thr_name, "s.a", &s.a, 0x20);
+  check_alignment (thr_name, "s.b", &s.b, 0x200);
+}
+
+static void *
+tf (void *arg)
+{
+  check_s ("child");
+
+  ++s.a;
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  check_s ("main");
+
+  pthread_attr_t a;
+
+  xpthread_attr_init (&a);
+
+#define STACK_SIZE (1 * 1024 * 1024)
+  xpthread_attr_setstacksize (&a, STACK_SIZE);
+
+#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)
+	th[j] = xpthread_create (&a, tf, NULL);
+
+      for (j = 0; j < M; ++j)
+	xpthread_join (th[j]);
+    }
+
+  /* Also check the alignment of the tls variables if a misaligned stack is
+     specified.  */
+  pthread_t th;
+  void *thr_stack = NULL;
+  thr_stack = xposix_memalign (0x200, STACK_SIZE + 1);
+  xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE);
+  th = xpthread_create (&a, tf, NULL);
+  xpthread_join (th);
+  free (thr_stack);
+
+  xpthread_attr_destroy (&a);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-pt-tls2.c b/sysdeps/pthread/tst-pt-tls2.c
new file mode 100644
index 0000000000..f319707f86
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-tls2.c
@@ -0,0 +1,206 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <signal.h>
+#include <semaphore.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define N 10
+static pthread_t th[N];
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+#define CB(n) \
+static void								      \
+cb##n (void)								      \
+{									      \
+  if (th[n] != pthread_self ())						      \
+    {									      \
+      write_message ("wrong callback\n");				      \
+      _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_message ("wrong signal\n");
+      _exit (1);
+    }
+
+  fp ();
+
+  if (sem_post (&s) != 0)
+    {
+      write_message ("sem_post failed\n");
+      _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;
+}
+
+
+int
+do_test (void)
+{
+  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;
+}
diff --git a/sysdeps/pthread/tst-pt-vfork1.c b/sysdeps/pthread/tst-pt-vfork1.c
new file mode 100644
index 0000000000..f409ec49b3
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-vfork1.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork1.c>
diff --git a/sysdeps/pthread/tst-pt-vfork2.c b/sysdeps/pthread/tst-pt-vfork2.c
new file mode 100644
index 0000000000..5356e83115
--- /dev/null
+++ b/sysdeps/pthread/tst-pt-vfork2.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork2.c>
diff --git a/sysdeps/pthread/tst-raise1.c b/sysdeps/pthread/tst-raise1.c
new file mode 100644
index 0000000000..f015cf3ff6
--- /dev/null
+++ b/sysdeps/pthread/tst-raise1.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <error.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+volatile int count;
+
+void
+sh (int sig)
+{
+  ++count;
+}
+
+int
+main (void)
+{
+  struct sigaction sa;
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (SIGUSR1, &sa, NULL) < 0)
+    {
+      printf ("sigaction failed: %m\n");
+      exit (1);
+    }
+  if (raise (SIGUSR1) < 0)
+    {
+      printf ("first raise failed: %m\n");
+      exit (1);
+    }
+  if (raise (SIGUSR1) < 0)
+    {
+      printf ("second raise failed: %m\n");
+      exit (1);
+    }
+  if (count != 2)
+    {
+      printf ("signal handler not called 2 times\n");
+      exit (1);
+    }
+  exit (0);
+}
diff --git a/sysdeps/pthread/tst-setuid3.c b/sysdeps/pthread/tst-setuid3.c
new file mode 100644
index 0000000000..261c265664
--- /dev/null
+++ b/sysdeps/pthread/tst-setuid3.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2014-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+/* The test must run under a non-privileged user ID.  */
+static const uid_t test_uid = 1;
+
+static pthread_barrier_t barrier1;
+static pthread_barrier_t barrier2;
+
+#define FAIL(fmt, ...) \
+  do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
+
+#define FAIL_ERR(fmt, ...) \
+  do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
+
+/* True if x is not a successful return code from pthread_barrier_wait.  */
+static inline bool
+is_invalid_barrier_ret (int x)
+{
+  return x != 0 && x != PTHREAD_BARRIER_SERIAL_THREAD;
+}
+
+static void *
+thread_func (void *ctx __attribute__ ((unused)))
+{
+  int ret = pthread_barrier_wait (&barrier1);
+  if (is_invalid_barrier_ret (ret))
+    FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
+  ret = pthread_barrier_wait (&barrier2);
+  if (is_invalid_barrier_ret (ret))
+    FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
+  return NULL;
+}
+
+static void
+setuid_failure (int phase)
+{
+  int ret = setuid (0);
+  switch (ret)
+    {
+    case 0:
+      FAIL ("setuid succeeded unexpectedly in phase %d", phase);
+    case -1:
+      if (errno != EPERM)
+	FAIL_ERR ("setuid phase %d", phase);
+      break;
+    default:
+      FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
+    }
+}
+
+static int
+do_test (void)
+{
+  if (getuid () == 0)
+    if (setuid (test_uid) != 0)
+      FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
+  if (setuid (getuid ()))
+    FAIL_ERR ("setuid (%s)", "getuid ()");
+  setuid_failure (1);
+
+  int ret = pthread_barrier_init (&barrier1, NULL, 2);
+  if (ret != 0)
+    FAIL ("pthread_barrier_init (barrier1): %d", ret);
+  ret = pthread_barrier_init (&barrier2, NULL, 2);
+  if (ret != 0)
+    FAIL ("pthread_barrier_init (barrier2): %d", ret);
+
+  pthread_t thread;
+  ret = pthread_create (&thread, NULL, thread_func, NULL);
+  if (ret != 0)
+    FAIL ("pthread_create: %d", ret);
+
+  /* Ensure that the thread is running properly.  */
+  ret = pthread_barrier_wait (&barrier1);
+  if (is_invalid_barrier_ret (ret))
+    FAIL ("pthread_barrier_wait (barrier1): %d", ret);
+
+  setuid_failure (2);
+
+  /* Check success case. */
+  if (setuid (getuid ()) != 0)
+    FAIL_ERR ("setuid (%s)", "getuid ()");
+
+  /* Shutdown.  */
+  ret = pthread_barrier_wait (&barrier2);
+  if (is_invalid_barrier_ret (ret))
+    FAIL ("pthread_barrier_wait (barrier2): %d", ret);
+
+  ret = pthread_join (thread, NULL);
+  if (ret != 0)
+    FAIL ("pthread_join: %d", ret);
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-signal4.c b/sysdeps/pthread/tst-signal4.c
new file mode 100644
index 0000000000..e6e837a912
--- /dev/null
+++ b/sysdeps/pthread/tst-signal4.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-signal5.c b/sysdeps/pthread/tst-signal5.c
new file mode 100644
index 0000000000..114bf060bc
--- /dev/null
+++ b/sysdeps/pthread/tst-signal5.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-signal6.c b/sysdeps/pthread/tst-signal6.c
new file mode 100644
index 0000000000..fcf703127b
--- /dev/null
+++ b/sysdeps/pthread/tst-signal6.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#ifdef SIGRTMIN
+
+# define N 2
+static pthread_barrier_t bar;
+static struct
+{
+  void *p;
+  pthread_t s;
+} ti[N];
+static int sig1;
+
+
+static void
+handler (int sig)
+{
+  pthread_t self = pthread_self ();
+  size_t i;
+
+  for (i = 0; i < N; ++i)
+    if (ti[i].s == self)
+      {
+	if ((uintptr_t) ti[i].p <= (uintptr_t) &self
+	    && (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
+	  {
+	    puts ("alt stack not used");
+	    exit (1);
+	  }
+
+	printf ("thread %zu used alt stack for signal %d\n", i, sig);
+
+	return;
+      }
+
+  puts ("handler: thread not found");
+  exit (1);
+}
+
+
+static void *
+tf (void *arg)
+{
+  size_t nr = (uintptr_t) arg;
+  if (nr >= N)
+    {
+      puts ("wrong nr parameter");
+      exit (1);
+    }
+
+  sigset_t ss;
+  sigemptyset (&ss);
+  size_t i;
+  for (i = 0; i < N; ++i)
+    if (i != nr)
+      if (sigaddset (&ss, sig1 + i) != 0)
+	{
+	  puts ("tf: sigaddset failed");
+	  exit (1);
+	}
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("tf: sigmask failed");
+      exit (1);
+    }
+
+  void *p = malloc (2 * MINSIGSTKSZ);
+  if (p == NULL)
+    {
+      puts ("tf: malloc failed");
+      exit (1);
+    }
+
+  stack_t s;
+  s.ss_sp = p;
+  s.ss_size = 2 * MINSIGSTKSZ;
+  s.ss_flags = 0;
+  if (sigaltstack (&s, NULL) != 0)
+    {
+      puts ("tf: sigaltstack failed");
+      exit (1);
+    }
+
+  ti[nr].p = p;
+  ti[nr].s = pthread_self ();
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  sig1 = SIGRTMIN;
+  if (sig1 + N > SIGRTMAX)
+    {
+      puts ("too few RT signals");
+      return 0;
+    }
+
+  struct sigaction sa;
+  sa.sa_handler = handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+
+  if (sigaction (sig1, &sa, NULL) != 0
+      || sigaction (sig1 + 1, &sa, NULL) != 0
+      || sigaction (sig1 + 2, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th[N];
+  size_t i;
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
+      {
+	puts ("create failed");
+	return 1;
+      }
+
+  /* Block the three signals.  */
+  sigset_t ss;
+  sigemptyset (&ss);
+  for (i = 0; i <= N; ++i)
+    sigaddset (&ss, sig1 + i);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("main: sigmask failed");
+      return 1;
+    }
+
+  pthread_barrier_wait (&bar);
+
+  /* Send some signals.  */
+  pid_t me = getpid ();
+  kill (me, sig1 + N);
+  for (i = 0; i < N; ++i)
+    kill (me, sig1 + i);
+  kill (me, sig1 + N);
+
+  /* Give the signals a chance to be worked on.  */
+  sleep (1);
+
+  pthread_barrier_wait (&bar);
+
+  for (i = 0; i < N; ++i)
+    if (pthread_join (th[i], NULL) != 0)
+      {
+	puts ("join failed");
+	return 1;
+      }
+
+  return 0;
+}
+
+# define TEST_FUNCTION do_test ()
+
+#else
+# define TEST_FUNCTION 0
+#endif
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-signal8.c b/sysdeps/pthread/tst-signal8.c
new file mode 100644
index 0000000000..9da7e5ef07
--- /dev/null
+++ b/sysdeps/pthread/tst-signal8.c
@@ -0,0 +1,62 @@
+/* Tests for sigisemptyset and pthread_sigmask.
+   Copyright (C) 2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+
+#include <support/check.h>
+#include <support/xthread.h>
+
+static void *
+tf (void *arg)
+{
+  {
+    sigset_t set;
+    sigemptyset (&set);
+    TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
+    TEST_COMPARE (sigisemptyset (&set), 1);
+  }
+
+  {
+    sigset_t set;
+    sigfillset (&set);
+    TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
+    TEST_COMPARE (sigisemptyset (&set), 1);
+  }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  /* Ensure current SIG_BLOCK mask empty.  */
+  {
+    sigset_t set;
+    sigemptyset (&set);
+    TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0);
+  }
+
+  {
+    pthread_t thr = xpthread_create (NULL, tf, NULL);
+    xpthread_join (thr);
+  }
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-stack1.c b/sysdeps/pthread/tst-stack1.c
new file mode 100644
index 0000000000..7285a9cbc9
--- /dev/null
+++ b/sysdeps/pthread/tst-stack1.c
@@ -0,0 +1,148 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <limits.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+
+static void *stack;
+static size_t size;
+
+
+static void *
+tf (void *a)
+{
+  int result = 0;
+
+  puts ("child start");
+
+  pthread_attr_t attr;
+  if (pthread_getattr_np (pthread_self (), &attr) != 0)
+    {
+      puts ("getattr_np failed");
+      exit (1);
+    }
+
+  size_t test_size;
+  void *test_stack;
+  if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+    {
+      puts ("attr_getstack failed");
+      exit (1);
+    }
+
+  if (test_size != size)
+    {
+      printf ("child: reported size differs: is %zu, expected %zu\n",
+	      test_size, size);
+      result = 1;
+    }
+
+  if (test_stack != stack)
+    {
+      printf ("child: reported stack address differs: is %p, expected %p\n",
+	      test_stack, stack);
+      result = 1;
+    }
+
+  puts ("child OK");
+
+  return result ? (void *) 1l : NULL;
+}
+
+
+int
+do_test (void)
+{
+  int result = 0;
+
+  size = 4 * getpagesize ();
+#ifdef PTHREAD_STACK_MIN
+  size = MAX (size, PTHREAD_STACK_MIN);
+#endif
+  if (posix_memalign (&stack, getpagesize (), size) != 0)
+    {
+      puts ("out of memory while allocating the stack memory");
+      exit (1);
+    }
+
+  pthread_attr_t attr;
+  if (pthread_attr_init (&attr) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  puts ("attr_setstack");
+  if (pthread_attr_setstack (&attr, stack, size) != 0)
+    {
+      puts ("attr_setstack failed");
+      exit (1);
+    }
+
+  size_t test_size;
+  void *test_stack;
+  puts ("attr_getstack");
+  if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+    {
+      puts ("attr_getstack failed");
+      exit (1);
+    }
+
+  if (test_size != size)
+    {
+      printf ("reported size differs: is %zu, expected %zu\n",
+	      test_size, size);
+      result = 1;
+    }
+
+  if (test_stack != stack)
+    {
+      printf ("reported stack address differs: is %p, expected %p\n",
+	      test_stack, stack);
+      result = 1;
+    }
+
+  puts ("create");
+
+  pthread_t th;
+  if (pthread_create (&th, &attr, tf, NULL) != 0)
+    {
+      puts ("failed to create thread");
+      exit (1);
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  result |= status != NULL;
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-stdio1.c b/sysdeps/pthread/tst-stdio1.c
new file mode 100644
index 0000000000..66696a92ee
--- /dev/null
+++ b/sysdeps/pthread/tst-stdio1.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void *tf (void *a)
+{
+  flockfile (stdout);
+  /* This call should never return.  */
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  flockfile (stdout);
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write_message ("create failed\n");
+      _exit (1);
+    }
+
+  delayed_exit (1);
+  xpthread_join (th);
+
+  puts ("join returned");
+
+  return 1;
+}
diff --git a/sysdeps/pthread/tst-stdio2.c b/sysdeps/pthread/tst-stdio2.c
new file mode 100644
index 0000000000..343b34ce83
--- /dev/null
+++ b/sysdeps/pthread/tst-stdio2.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+static int do_test (void);
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
+
+static void *tf (void *a)
+{
+  puts ("start tf");
+
+  /* Multiple locking, implicitly or explicitly, must be possible.  */
+  flockfile (stdout);
+
+  puts ("after first flockfile");
+
+  flockfile (stdout);
+
+  puts ("foo");
+
+  funlockfile (stdout);
+
+  puts ("after first funlockfile");
+
+  funlockfile (stdout);
+
+  puts ("all done");
+
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write_message ("create failed\n");
+      _exit (1);
+    }
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+  else if (result != NULL)
+    {
+      printf ("wrong return value: %p, expected %p\n", result, NULL);
+      exit (1);
+    }
+
+  puts ("join returned succsefully");
+
+  return 0;
+}
diff --git a/sysdeps/pthread/tst-tsd1.c b/sysdeps/pthread/tst-tsd1.c
new file mode 100644
index 0000000000..3e97dea078
--- /dev/null
+++ b/sysdeps/pthread/tst-tsd1.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-tsd2.c b/sysdeps/pthread/tst-tsd2.c
new file mode 100644
index 0000000000..f72da40c84
--- /dev/null
+++ b/sysdeps/pthread/tst-tsd2.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2002-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#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/sysdeps/pthread/tst-tsd5.c b/sysdeps/pthread/tst-tsd5.c
new file mode 100644
index 0000000000..e439588329
--- /dev/null
+++ b/sysdeps/pthread/tst-tsd5.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2004-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *p)
+{
+  pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_key_t k;
+  if (pthread_key_create (&k, cl) != 0)
+    {
+      puts ("key_create failed");
+      return 1;
+    }
+  if (pthread_setspecific (k, (void *) 1) != 0)
+    {
+      puts ("setspecific failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  pthread_exit (NULL);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-tsd6.c b/sysdeps/pthread/tst-tsd6.c
new file mode 100644
index 0000000000..debb1dd367
--- /dev/null
+++ b/sysdeps/pthread/tst-tsd6.c
@@ -0,0 +1,89 @@
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define NKEYS 100
+static pthread_key_t keys[NKEYS];
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  void *res = NULL;
+  for (int i = 0; i < NKEYS; ++i)
+    {
+      void *p = pthread_getspecific (keys[i]);
+      pthread_setspecific (keys[i], (void *) 7);
+      if (p != NULL)
+	res = p;
+    }
+  if (arg != NULL)
+    {
+      pthread_barrier_wait (arg);
+      pthread_barrier_wait (arg);
+    }
+  return res;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_barrier_init (&b, NULL, 2);
+
+  for (int i = 0; i < NKEYS; ++i)
+    if (pthread_key_create (&keys[i], NULL) != 0)
+      {
+	puts ("cannot create keys");
+	return 1;
+      }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &b) != 0)
+    {
+      puts ("cannot create thread in parent");
+      return 1;
+    }
+
+  pthread_barrier_wait (&b);
+
+  pid_t pid = fork ();
+  if (pid == 0)
+    {
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("cannot create thread in child");
+	  exit (1);
+	}
+
+      void *res;
+      pthread_join (th, &res);
+
+      exit (res != NULL);
+    }
+  else if (pid == -1)
+    {
+      puts ("cannot create child process");
+      return 1;
+    }
+
+  int s;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
+    {
+      puts ("failing to wait for child process");
+      return 1;
+    }
+
+  pthread_barrier_wait (&b);
+  pthread_join (th, NULL);
+
+  return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-umask1.c b/sysdeps/pthread/tst-umask1.c
new file mode 100644
index 0000000000..46ff89b9fd
--- /dev/null
+++ b/sysdeps/pthread/tst-umask1.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2003-2020 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, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+static struct
+{
+  int (*fp) (const char *, mode_t);
+  const char *name;
+  bool is_fd;
+} fcts[] =
+{
+  { creat, "creat", true },
+  { mkdir, "mkdir", false },
+  { mkfifo, "mkfifo", false },
+};
+#define nfcts (sizeof (fcts) / sizeof (fcts[0]))
+
+
+static int
+work (const char *fname, int mask)
+{
+  int result = 0;
+  size_t i;
+  for (i = 0; i < nfcts; ++i)
+    {
+      remove (fname);
+      int fd = fcts[i].fp (fname, 0777);
+      if (fd == -1)
+	{
+	  printf ("cannot %s %s: %m\n", fcts[i].name, fname);
+	  exit (1);
+	}
+      if (fcts[i].is_fd)
+	close (fd);
+      struct stat64 st;
+      if (stat64 (fname, &st) == -1)
+	{
+	  printf ("cannot stat %s after %s: %m\n", fname, fcts[i].name);
+	  exit (1);
+	}
+
+      if ((st.st_mode & mask) != 0)
+	{
+	  printf ("mask not successful after %s: %x still set\n",
+		  fcts[i].name, (unsigned int) (st.st_mode & mask));
+	  result = 1;
+	}
+    }
+
+  return result;
+}
+
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *arg)
+{
+  pthread_barrier_wait (&bar);
+
+  int result = work (arg, 022);
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  return (work (arg, 0) | result) ? (void *) -1l : NULL;
+}
+
+
+static int
+do_test (const char *fname)
+{
+  int result = 0;
+
+  umask (0);
+  result |= work (fname, 0);
+
+  pthread_barrier_init (&bar, NULL, 2);
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, (void *) fname) != 0)
+    {
+      puts ("cannot create thread");
+      exit (1);
+    }
+
+  umask (022);
+  result |= work (fname, 022);
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  umask (0);
+
+  pthread_barrier_wait (&bar);
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  remove (fname);
+
+  return result || res != NULL;
+}
+
+#define TEST_FUNCTION do_test (argc < 2 ? "/tmp/tst-umask.tmp" : argv[1])
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-unload.c b/sysdeps/pthread/tst-unload.c
new file mode 100644
index 0000000000..b29745c9c1
--- /dev/null
+++ b/sysdeps/pthread/tst-unload.c
@@ -0,0 +1,47 @@
+/* Tests for non-unloading of libpthread.
+   Copyright (C) 2000-2020 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, see <https://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gnu/lib-names.h>
+
+static int
+do_test (void)
+{
+  void *p = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
+
+  if (p == NULL)
+    {
+      puts ("failed to load " LIBPTHREAD_SO);
+      return 1;
+    }
+
+  if (dlclose (p) != 0)
+    {
+      puts ("dlclose (" LIBPTHREAD_SO ") failed");
+      return 1;
+    }
+
+  puts ("seems to work");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/pthread/tst-unwind-thread.c b/sysdeps/pthread/tst-unwind-thread.c
new file mode 100644
index 0000000000..d5c38e3709
--- /dev/null
+++ b/sysdeps/pthread/tst-unwind-thread.c
@@ -0,0 +1,2 @@
+#define USE_PTHREADS 1
+#include "../elf/tst-unwind-main.c"
diff --git a/sysdeps/pthread/tst-vfork1x.c b/sysdeps/pthread/tst-vfork1x.c
new file mode 100644
index 0000000000..f409ec49b3
--- /dev/null
+++ b/sysdeps/pthread/tst-vfork1x.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork1.c>
diff --git a/sysdeps/pthread/tst-vfork2x.c b/sysdeps/pthread/tst-vfork2x.c
new file mode 100644
index 0000000000..5356e83115
--- /dev/null
+++ b/sysdeps/pthread/tst-vfork2x.c
@@ -0,0 +1 @@
+#include <posix/tst-vfork2.c>