aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/pthread
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/pthread
parentbe22a151f3e2c2e4b9127d4fa30b269f30a7ea2e (diff)
downloadglibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.tar
glibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.tar.gz
glibc-d6d74ec16c77126c59db264ebfa04d08d5b4c5c0.tar.bz2
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/pthread')
-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>