aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/pthread
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-01-13 19:58:28 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-02-09 13:56:48 +0100
commitb05de1040009d0d07a5a2e2765cffe554ffbe6ac (patch)
tree2b112a97ce7947699fac8b6df47e6db0b5196ded /sysdeps/pthread
parent6cefe985b869e7b33b05ce7252410474d8a6c3ad (diff)
downloadglibc-b05de1040009d0d07a5a2e2765cffe554ffbe6ac.tar
glibc-b05de1040009d0d07a5a2e2765cffe554ffbe6ac.tar.gz
glibc-b05de1040009d0d07a5a2e2765cffe554ffbe6ac.tar.bz2
glibc-b05de1040009d0d07a5a2e2765cffe554ffbe6ac.zip
C11 threads: Move implementation to sysdeps/pthread
so it gets shared by nptl and htl. Also add htl versions of thrd_current and thrd_yield. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps/pthread')
-rw-r--r--sysdeps/pthread/Makefile18
-rw-r--r--sysdeps/pthread/call_once.c31
-rw-r--r--sysdeps/pthread/cnd_broadcast.c26
-rw-r--r--sysdeps/pthread/cnd_destroy.c26
-rw-r--r--sysdeps/pthread/cnd_init.c33
-rw-r--r--sysdeps/pthread/cnd_signal.c26
-rw-r--r--sysdeps/pthread/cnd_timedwait.c29
-rw-r--r--sysdeps/pthread/cnd_wait.c27
-rw-r--r--sysdeps/pthread/mtx_destroy.c26
-rw-r--r--sysdeps/pthread/mtx_init.c53
-rw-r--r--sysdeps/pthread/mtx_lock.c26
-rw-r--r--sysdeps/pthread/mtx_timedlock.c28
-rw-r--r--sysdeps/pthread/mtx_trylock.c26
-rw-r--r--sysdeps/pthread/mtx_unlock.c26
-rw-r--r--sysdeps/pthread/thrd_create.c30
-rw-r--r--sysdeps/pthread/thrd_detach.c28
-rw-r--r--sysdeps/pthread/thrd_equal.c25
-rw-r--r--sysdeps/pthread/thrd_exit.c25
-rw-r--r--sysdeps/pthread/thrd_join.c30
-rw-r--r--sysdeps/pthread/thrd_priv.h45
-rw-r--r--sysdeps/pthread/thrd_sleep.c36
-rw-r--r--sysdeps/pthread/threads.h204
-rw-r--r--sysdeps/pthread/tss_create.c33
-rw-r--r--sysdeps/pthread/tss_delete.c25
-rw-r--r--sysdeps/pthread/tss_get.c25
-rw-r--r--sysdeps/pthread/tss_set.c26
-rw-r--r--sysdeps/pthread/tst-call-once.c66
-rw-r--r--sysdeps/pthread/tst-cnd-basic.c80
-rw-r--r--sysdeps/pthread/tst-cnd-broadcast.c97
-rw-r--r--sysdeps/pthread/tst-cnd-timedwait.c84
-rw-r--r--sysdeps/pthread/tst-mtx-basic.c73
-rw-r--r--sysdeps/pthread/tst-mtx-recursive.c45
-rw-r--r--sysdeps/pthread/tst-mtx-timedlock.c103
-rw-r--r--sysdeps/pthread/tst-mtx-trylock.c90
-rw-r--r--sysdeps/pthread/tst-thrd-detach.c52
-rw-r--r--sysdeps/pthread/tst-thrd-sleep.c51
-rw-r--r--sysdeps/pthread/tst-tss-basic.c75
37 files changed, 1749 insertions, 0 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
index 7f9eadd0e2..889f10d8b1 100644
--- a/sysdeps/pthread/Makefile
+++ b/sysdeps/pthread/Makefile
@@ -25,3 +25,21 @@ $(objpfx)tst-timer: $(objpfx)librt.a $(static-thread-library)
endif
endif
+
+ifneq (,$(filter $(subdir),htl nptl))
+headers += threads.h
+
+routines += thrd_current thrd_equal thrd_sleep thrd_yield
+
+libpthread-routines += thrd_create thrd_detach thrd_exit thrd_join \
+ call_once \
+ mtx_destroy mtx_init mtx_lock mtx_timedlock \
+ mtx_trylock mtx_unlock \
+ cnd_broadcast \
+ cnd_destroy cnd_init cnd_signal cnd_timedwait cnd_wait \
+ tss_create tss_delete tss_get tss_set
+
+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
+endif
diff --git a/sysdeps/pthread/call_once.c b/sysdeps/pthread/call_once.c
new file mode 100644
index 0000000000..25e2964c76
--- /dev/null
+++ b/sysdeps/pthread/call_once.c
@@ -0,0 +1,31 @@
+/* C11 threads call once implementation.
+ Copyright (C) 2018-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 <stdalign.h>
+
+#include "thrd_priv.h"
+
+void
+call_once (once_flag *flag, void (*func)(void))
+{
+ _Static_assert (sizeof (once_flag) == sizeof (pthread_once_t),
+ "sizeof (once_flag) != sizeof (pthread_once_t)");
+ _Static_assert (alignof (once_flag) == alignof (pthread_once_t),
+ "alignof (once_flag) != alignof (pthread_once_t)");
+ __pthread_once ((pthread_once_t *) flag, func);
+}
diff --git a/sysdeps/pthread/cnd_broadcast.c b/sysdeps/pthread/cnd_broadcast.c
new file mode 100644
index 0000000000..66e0fce0c6
--- /dev/null
+++ b/sysdeps/pthread/cnd_broadcast.c
@@ -0,0 +1,26 @@
+/* C11 thread conditional broadcast implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+cnd_broadcast (cnd_t *cond)
+{
+ int err_code = __pthread_cond_broadcast ((pthread_cond_t*) cond);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/cnd_destroy.c b/sysdeps/pthread/cnd_destroy.c
new file mode 100644
index 0000000000..763e91cb0f
--- /dev/null
+++ b/sysdeps/pthread/cnd_destroy.c
@@ -0,0 +1,26 @@
+/* C11 threads conditional destroy implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+#include "pthreadP.h"
+
+void
+cnd_destroy (cnd_t *cond)
+{
+ __pthread_cond_destroy ((pthread_cond_t *) cond);
+}
diff --git a/sysdeps/pthread/cnd_init.c b/sysdeps/pthread/cnd_init.c
new file mode 100644
index 0000000000..e8d7d68a2c
--- /dev/null
+++ b/sysdeps/pthread/cnd_init.c
@@ -0,0 +1,33 @@
+/* C11 thread conditional initialization implementation.
+ Copyright (C) 2018-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 <stdalign.h>
+
+#include "thrd_priv.h"
+
+int
+cnd_init (cnd_t *cond)
+{
+ _Static_assert (sizeof (cnd_t) == sizeof (pthread_cond_t),
+ "(sizeof (cnd_t) != sizeof (pthread_cond_t)");
+ _Static_assert (alignof (cnd_t) == alignof (pthread_cond_t),
+ "alignof (cnd_t) != alignof (pthread_cond_t)");
+
+ int err_code = __pthread_cond_init ((pthread_cond_t *)cond, NULL);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/cnd_signal.c b/sysdeps/pthread/cnd_signal.c
new file mode 100644
index 0000000000..27155ffc1b
--- /dev/null
+++ b/sysdeps/pthread/cnd_signal.c
@@ -0,0 +1,26 @@
+/* C11 threads conditional signal implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+cnd_signal (cnd_t *cond)
+{
+ int err_code = __pthread_cond_signal ((pthread_cond_t *) cond);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/cnd_timedwait.c b/sysdeps/pthread/cnd_timedwait.c
new file mode 100644
index 0000000000..c7f5309cf7
--- /dev/null
+++ b/sysdeps/pthread/cnd_timedwait.c
@@ -0,0 +1,29 @@
+/* C11 threads conditional timed wait implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+cnd_timedwait (cnd_t *restrict cond, mtx_t *restrict mutex,
+ const struct timespec* restrict time_point)
+{
+ int err_code = __pthread_cond_timedwait ((pthread_cond_t *) cond,
+ (pthread_mutex_t *) mutex,
+ time_point);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/cnd_wait.c b/sysdeps/pthread/cnd_wait.c
new file mode 100644
index 0000000000..8070ca7c6a
--- /dev/null
+++ b/sysdeps/pthread/cnd_wait.c
@@ -0,0 +1,27 @@
+/* C11 threads conditional wait implementaiton.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+cnd_wait (cnd_t *cond, mtx_t *mutex)
+{
+ int err_code = __pthread_cond_wait ((pthread_cond_t *) cond,
+ (pthread_mutex_t *) mutex);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/mtx_destroy.c b/sysdeps/pthread/mtx_destroy.c
new file mode 100644
index 0000000000..9ac324c8f8
--- /dev/null
+++ b/sysdeps/pthread/mtx_destroy.c
@@ -0,0 +1,26 @@
+/* C11 threads mutex destroy implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+#include "pthreadP.h"
+
+void
+mtx_destroy (mtx_t *mutex)
+{
+ __pthread_mutex_destroy ((pthread_mutex_t *) mutex);
+}
diff --git a/sysdeps/pthread/mtx_init.c b/sysdeps/pthread/mtx_init.c
new file mode 100644
index 0000000000..436a03673e
--- /dev/null
+++ b/sysdeps/pthread/mtx_init.c
@@ -0,0 +1,53 @@
+/* C11 threads mutex initialization implementation.
+ Copyright (C) 2018-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 <stdalign.h>
+
+#include "thrd_priv.h"
+
+int
+mtx_init (mtx_t *mutex, int type)
+{
+ _Static_assert (sizeof (mtx_t) == sizeof (pthread_mutex_t),
+ "sizeof (mtx_t) != sizeof (pthread_mutex_t)");
+ _Static_assert (alignof (mtx_t) == alignof (pthread_mutex_t),
+ "alignof (mtx_t) != alignof (pthread_mutex_t)");
+
+ pthread_mutexattr_t attr;
+
+ __pthread_mutexattr_init (&attr);
+
+ /* Another possible solution would be to set the flags directly in
+ mutex object. */
+ switch (type)
+ {
+ case mtx_plain | mtx_recursive:
+ case mtx_timed | mtx_recursive:
+ __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
+ break;
+ case mtx_plain:
+ case mtx_timed: /* No difference between both in standard */
+ default:
+ __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_NORMAL);
+ break;
+ }
+
+ int err_code = __pthread_mutex_init ((pthread_mutex_t *) mutex, &attr);
+ /* pthread_mutexattr_destroy implementation is a noop. */
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/mtx_lock.c b/sysdeps/pthread/mtx_lock.c
new file mode 100644
index 0000000000..cf1632b3f2
--- /dev/null
+++ b/sysdeps/pthread/mtx_lock.c
@@ -0,0 +1,26 @@
+/* C11 threads mutex lock implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+mtx_lock (mtx_t *mutex)
+{
+ int err_code = __pthread_mutex_lock ((pthread_mutex_t *) mutex);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/mtx_timedlock.c b/sysdeps/pthread/mtx_timedlock.c
new file mode 100644
index 0000000000..d55cf99d11
--- /dev/null
+++ b/sysdeps/pthread/mtx_timedlock.c
@@ -0,0 +1,28 @@
+/* C11 threads mutex timed lock implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+mtx_timedlock (mtx_t *restrict mutex,
+ const struct timespec *restrict time_point)
+{
+ int err_code = __pthread_mutex_timedlock ((pthread_mutex_t *)mutex,
+ time_point);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/mtx_trylock.c b/sysdeps/pthread/mtx_trylock.c
new file mode 100644
index 0000000000..7ffcbc1e93
--- /dev/null
+++ b/sysdeps/pthread/mtx_trylock.c
@@ -0,0 +1,26 @@
+/* C11 threads mutex try lock implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+mtx_trylock (mtx_t *mutex)
+{
+ int err_code = __pthread_mutex_trylock ((pthread_mutex_t *) mutex);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/mtx_unlock.c b/sysdeps/pthread/mtx_unlock.c
new file mode 100644
index 0000000000..ebb0cd633b
--- /dev/null
+++ b/sysdeps/pthread/mtx_unlock.c
@@ -0,0 +1,26 @@
+/* C11 threads mutex unlock implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+mtx_unlock (mtx_t *mutex)
+{
+ int err_code = __pthread_mutex_unlock ((pthread_mutex_t *) mutex);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/thrd_create.c b/sysdeps/pthread/thrd_create.c
new file mode 100644
index 0000000000..4c47f053af
--- /dev/null
+++ b/sysdeps/pthread/thrd_create.c
@@ -0,0 +1,30 @@
+/* C11 threads thread creation implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
+{
+ _Static_assert (sizeof (thrd_t) == sizeof (pthread_t),
+ "sizeof (thrd_t) != sizeof (pthread_t)");
+
+ int err_code = __pthread_create (thr, ATTR_C11_THREAD,
+ (void* (*) (void*))func, arg);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/thrd_detach.c b/sysdeps/pthread/thrd_detach.c
new file mode 100644
index 0000000000..8ddc2e8477
--- /dev/null
+++ b/sysdeps/pthread/thrd_detach.c
@@ -0,0 +1,28 @@
+/* C11 threads thread detach implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+thrd_detach (thrd_t thr)
+{
+ int err_code;
+
+ err_code = __pthread_detach (thr);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/thrd_equal.c b/sysdeps/pthread/thrd_equal.c
new file mode 100644
index 0000000000..41211d3ef9
--- /dev/null
+++ b/sysdeps/pthread/thrd_equal.c
@@ -0,0 +1,25 @@
+/* C11 threads thread equality check implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+thrd_equal (thrd_t lhs, thrd_t rhs)
+{
+ return lhs == rhs;
+}
diff --git a/sysdeps/pthread/thrd_exit.c b/sysdeps/pthread/thrd_exit.c
new file mode 100644
index 0000000000..d9ad207baa
--- /dev/null
+++ b/sysdeps/pthread/thrd_exit.c
@@ -0,0 +1,25 @@
+/* C11 threads thread exit implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+_Noreturn void
+thrd_exit (int res)
+{
+ __pthread_exit ((void*)(uintptr_t) res);
+}
diff --git a/sysdeps/pthread/thrd_join.c b/sysdeps/pthread/thrd_join.c
new file mode 100644
index 0000000000..0c482959d5
--- /dev/null
+++ b/sysdeps/pthread/thrd_join.c
@@ -0,0 +1,30 @@
+/* C11 threads thread join implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+thrd_join (thrd_t thr, int *res)
+{
+ void *pthread_res;
+ int err_code = __pthread_join (thr, &pthread_res);
+ if (res)
+ *res = (int) (uintptr_t) pthread_res;
+
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/thrd_priv.h b/sysdeps/pthread/thrd_priv.h
new file mode 100644
index 0000000000..d22ad6f632
--- /dev/null
+++ b/sysdeps/pthread/thrd_priv.h
@@ -0,0 +1,45 @@
+/* Internal C11 threads definitions.
+ Copyright (C) 2018-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/>. */
+
+#ifndef THRD_PRIV_H
+# define THRD_PRIV_H
+
+#include <features.h>
+#include <threads.h>
+#include <errno.h>
+#include "pthreadP.h" /* For pthread_{mutex,cond}_t definitions. */
+
+static __always_inline int
+thrd_err_map (int err_code)
+{
+ switch (err_code)
+ {
+ case 0:
+ return thrd_success;
+ case ENOMEM:
+ return thrd_nomem;
+ case ETIMEDOUT:
+ return thrd_timedout;
+ case EBUSY:
+ return thrd_busy;
+ default:
+ return thrd_error;
+ }
+}
+
+#endif
diff --git a/sysdeps/pthread/thrd_sleep.c b/sysdeps/pthread/thrd_sleep.c
new file mode 100644
index 0000000000..c9805d5fd1
--- /dev/null
+++ b/sysdeps/pthread/thrd_sleep.c
@@ -0,0 +1,36 @@
+/* C11 threads thread sleep implementation.
+ Copyright (C) 2018-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 <time.h>
+#include <sysdep-cancel.h>
+
+#include "thrd_priv.h"
+
+int
+thrd_sleep (const struct timespec* time_point, struct timespec* remaining)
+{
+ int ret = __clock_nanosleep (CLOCK_REALTIME, 0, time_point, remaining);
+ /* C11 states thrd_sleep function returns -1 if it has been interrupted
+ by a signal, or a negative value if it fails. */
+ switch (ret)
+ {
+ case 0: return 0;
+ case EINTR: return -1;
+ default: return -2;
+ }
+}
diff --git a/sysdeps/pthread/threads.h b/sysdeps/pthread/threads.h
new file mode 100644
index 0000000000..0ac489b4a1
--- /dev/null
+++ b/sysdeps/pthread/threads.h
@@ -0,0 +1,204 @@
+/* ISO C11 Standard: 7.26 - Thread support library <threads.h>.
+ Copyright (C) 2018-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/>. */
+
+#ifndef _THREADS_H
+#define _THREADS_H 1
+
+#include <features.h>
+#include <time.h>
+
+__BEGIN_DECLS
+
+#include <bits/thread-shared-types.h>
+#include <bits/types/struct_timespec.h>
+
+#ifndef __cplusplus
+# define thread_local _Thread_local
+#endif
+
+#define TSS_DTOR_ITERATIONS 4
+typedef __tss_t tss_t;
+typedef void (*tss_dtor_t) (void*);
+
+typedef __thrd_t thrd_t;
+typedef int (*thrd_start_t) (void*);
+
+/* Exit and error codes. */
+enum
+{
+ thrd_success = 0,
+ thrd_busy = 1,
+ thrd_error = 2,
+ thrd_nomem = 3,
+ thrd_timedout = 4
+};
+
+/* Mutex types. */
+enum
+{
+ mtx_plain = 0,
+ mtx_recursive = 1,
+ mtx_timed = 2
+};
+
+typedef __once_flag once_flag;
+#define ONCE_FLAG_INIT __ONCE_FLAG_INIT
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_MUTEX_T];
+ long int __align __LOCK_ALIGNMENT;
+} mtx_t;
+
+typedef union
+{
+ char __size[__SIZEOF_PTHREAD_COND_T];
+ __extension__ long long int __align __LOCK_ALIGNMENT;
+} cnd_t;
+
+/* Threads functions. */
+
+/* Create a new thread executing the function __FUNC. Arguments for __FUNC
+ are passed through __ARG. If succesful, __THR is set to new thread
+ identifier. */
+extern int thrd_create (thrd_t *__thr, thrd_start_t __func, void *__arg);
+
+/* Check if __LHS and __RHS point to the same thread. */
+extern int thrd_equal (thrd_t __lhs, thrd_t __rhs);
+
+/* Return current thread identifier. */
+extern thrd_t thrd_current (void);
+
+/* Block current thread execution for at least the time pointed by
+ __TIME_POINT. The current thread may resume if receives a signal. In
+ that case, if __REMAINING is not NULL, the remaining time is stored in
+ the object pointed by it. */
+extern int thrd_sleep (const struct timespec *__time_point,
+ struct timespec *__remaining);
+
+/* Terminate current thread execution, cleaning up any thread local
+ storage and freeing resources. Returns the value specified in __RES. */
+extern void thrd_exit (int __res) __attribute__ ((__noreturn__));
+
+/* Detach the thread identified by __THR from the current environment
+ (it does not allow join or wait for it). */
+extern int thrd_detach (thrd_t __thr);
+
+/* Block current thread until execution of __THR is complete. In case that
+ __RES is not NULL, will store the return value of __THR when exiting. */
+extern int thrd_join (thrd_t __thr, int *__res);
+
+/* Stop current thread execution and call the scheduler to decide which
+ thread should execute next. The current thread may be selected by the
+ scheduler to keep running. */
+extern void thrd_yield (void);
+
+#ifdef __USE_EXTERN_INLINES
+/* Optimizations. */
+__extern_inline int
+thrd_equal (thrd_t __thread1, thrd_t __thread2)
+{
+ return __thread1 == __thread2;
+}
+#endif
+
+
+/* Mutex functions. */
+
+/* Creates a new mutex object with type __TYPE. If successful the new
+ object is pointed by __MUTEX. */
+extern int mtx_init (mtx_t *__mutex, int __type);
+
+/* Block the current thread until the mutex pointed to by __MUTEX is
+ unlocked. In that case current thread will not be blocked. */
+extern int mtx_lock (mtx_t *__mutex);
+
+/* Block the current thread until the mutex pointed by __MUTEX is unlocked
+ or time pointed by __TIME_POINT is reached. In case the mutex is unlock,
+ the current thread will not be blocked. */
+extern int mtx_timedlock (mtx_t *__restrict __mutex,
+ const struct timespec *__restrict __time_point);
+
+/* Try to lock the mutex pointed by __MUTEX without blocking. If the mutex
+ is free the current threads takes control of it, otherwise it returns
+ immediately. */
+extern int mtx_trylock (mtx_t *__mutex);
+
+/* Unlock the mutex pointed by __MUTEX. It may potentially awake other
+ threads waiting on this mutex. */
+extern int mtx_unlock (mtx_t *__mutex);
+
+/* Destroy the mutex object pointed by __MUTEX. */
+extern void mtx_destroy (mtx_t *__mutex);
+
+
+/* Call function __FUNC exactly once, even if invoked from several threads.
+ All calls must be made with the same __FLAGS object. */
+extern void call_once (once_flag *__flag, void (*__func)(void));
+
+
+/* Condition variable functions. */
+
+/* Initialize new condition variable pointed by __COND. */
+extern int cnd_init (cnd_t *__cond);
+
+/* Unblock one thread that currently waits on condition variable pointed
+ by __COND. */
+extern int cnd_signal (cnd_t *__cond);
+
+/* Unblock all threads currently waiting on condition variable pointed by
+ __COND. */
+extern int cnd_broadcast (cnd_t *__cond);
+
+/* Block current thread on the condition variable pointed by __COND. */
+extern int cnd_wait (cnd_t *__cond, mtx_t *__mutex);
+
+/* Block current thread on the condition variable until condition variable
+ pointed by __COND is signaled or time pointed by __TIME_POINT is
+ reached. */
+extern int cnd_timedwait (cnd_t *__restrict __cond,
+ mtx_t *__restrict __mutex,
+ const struct timespec *__restrict __time_point);
+
+/* Destroy condition variable pointed by __cond and free all of its
+ resources. */
+extern void cnd_destroy (cnd_t *__COND);
+
+
+/* Thread specific storage functions. */
+
+/* Create new thread-specific storage key and stores it in the object pointed
+ by __TSS_ID. If __DESTRUCTOR is not NULL, the function will be called when
+ the thread terminates. */
+extern int tss_create (tss_t *__tss_id, tss_dtor_t __destructor);
+
+/* Return the value held in thread-specific storage for the current thread
+ identified by __TSS_ID. */
+extern void *tss_get (tss_t __tss_id);
+
+/* Sets the value of the thread-specific storage identified by __TSS_ID for
+ the current thread to __VAL. */
+extern int tss_set (tss_t __tss_id, void *__val);
+
+/* Destroys the thread-specific storage identified by __TSS_ID. The
+ destructor is not called until thrd_exit is called. */
+extern void tss_delete (tss_t __tss_id);
+
+__END_DECLS
+
+#endif /* _THREADS_H */
diff --git a/sysdeps/pthread/tss_create.c b/sysdeps/pthread/tss_create.c
new file mode 100644
index 0000000000..4e170dd4fc
--- /dev/null
+++ b/sysdeps/pthread/tss_create.c
@@ -0,0 +1,33 @@
+/* C11 threads thread-specific creation implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+tss_create (tss_t *tss_id, tss_dtor_t destructor)
+{
+ _Static_assert (sizeof (tss_t) == sizeof (pthread_key_t),
+ "sizeof (tss_t) != sizeof (pthread_key_t)");
+#ifdef PTHREAD_DESTRUCTOR_ITERATIONS
+ _Static_assert (TSS_DTOR_ITERATIONS == PTHREAD_DESTRUCTOR_ITERATIONS,
+ "TSS_DTOR_ITERATIONS != PTHREAD_DESTRUCTOR_ITERATIONS");
+#endif
+
+ int err_code = __pthread_key_create (tss_id, destructor);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/tss_delete.c b/sysdeps/pthread/tss_delete.c
new file mode 100644
index 0000000000..38570ea100
--- /dev/null
+++ b/sysdeps/pthread/tss_delete.c
@@ -0,0 +1,25 @@
+/* C11 threads thread-specific delete implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+void
+tss_delete (tss_t tss_id)
+{
+ __pthread_key_delete (tss_id);
+}
diff --git a/sysdeps/pthread/tss_get.c b/sysdeps/pthread/tss_get.c
new file mode 100644
index 0000000000..f8300b7b84
--- /dev/null
+++ b/sysdeps/pthread/tss_get.c
@@ -0,0 +1,25 @@
+/* C11 threads thread-specific get implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+void *
+tss_get (tss_t tss_id)
+{
+ return __pthread_getspecific (tss_id);
+}
diff --git a/sysdeps/pthread/tss_set.c b/sysdeps/pthread/tss_set.c
new file mode 100644
index 0000000000..b21b6c2647
--- /dev/null
+++ b/sysdeps/pthread/tss_set.c
@@ -0,0 +1,26 @@
+/* C11 threads thread-specific set implementation.
+ Copyright (C) 2018-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 "thrd_priv.h"
+
+int
+tss_set (tss_t tss_id, void *val)
+{
+ int err_code = __pthread_setspecific (tss_id, val);
+ return thrd_err_map (err_code);
+}
diff --git a/sysdeps/pthread/tst-call-once.c b/sysdeps/pthread/tst-call-once.c
new file mode 100644
index 0000000000..c198233e8d
--- /dev/null
+++ b/sysdeps/pthread/tst-call-once.c
@@ -0,0 +1,66 @@
+/* C11 threads call_once test.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Flag that controls the first thread access. */
+static once_flag flag = ONCE_FLAG_INIT;
+
+static int value = 0;
+
+static void
+do_once (void)
+{
+ value++;
+}
+
+static int
+func (void* data)
+{
+ call_once (&flag, do_once);
+ thrd_exit (thrd_success);
+}
+
+#define N 20
+
+int
+do_test (void)
+{
+ thrd_t ids[N];
+
+ for (int i = 0; i < N; ++i)
+ {
+ if (thrd_create (&ids[i], func, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+ }
+
+ /* Join threads. */
+ for (int i = 0; i < N; ++i)
+ {
+ if (thrd_join (ids[i], NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+ }
+
+ return (value != 1);
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-cnd-basic.c b/sysdeps/pthread/tst-cnd-basic.c
new file mode 100644
index 0000000000..041762ae35
--- /dev/null
+++ b/sysdeps/pthread/tst-cnd-basic.c
@@ -0,0 +1,80 @@
+/* C11 threads condition variable tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared condition variable between child and parent. */
+static cnd_t cond;
+
+/* Mutex needed to signal and wait threads. */
+static mtx_t mutex;
+
+static int
+signal_parent (void)
+{
+ /* Acquire the lock so that cnd_signal does not run until
+ cnd_timedwait has been called. */
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+ if (cnd_signal (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_signal");
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ if (thrd_create (&id, (thrd_start_t) signal_parent, NULL)
+ != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (cnd_wait (&cond, &mutex) != thrd_success)
+ FAIL_EXIT1 ("cnd_wait failed");
+
+ /* Joining is not mandatory here, but still done to assure child thread
+ ends correctly. */
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock");
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-cnd-broadcast.c b/sysdeps/pthread/tst-cnd-broadcast.c
new file mode 100644
index 0000000000..ccc8504f6f
--- /dev/null
+++ b/sysdeps/pthread/tst-cnd-broadcast.c
@@ -0,0 +1,97 @@
+/* C11 threads condition broadcast variable tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Condition variable where child threads will wait. */
+static cnd_t cond;
+
+/* Mutex to control wait on cond. */
+static mtx_t mutex;
+
+/* Number of threads which have entered the cnd_wait region. */
+static unsigned int waiting_threads;
+
+/* Code executed by each thread. */
+static int
+child_wait (void* data)
+{
+ /* Wait until parent thread sends broadcast here. */
+ mtx_lock (&mutex);
+ ++waiting_threads;
+ cnd_wait (&cond, &mutex);
+ mtx_unlock (&mutex);
+
+ thrd_exit (thrd_success);
+}
+
+#define N 5
+
+static int
+do_test (void)
+{
+ thrd_t ids[N];
+ unsigned char i;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ /* Create N new threads. */
+ for (i = 0; i < N; ++i)
+ {
+ if (thrd_create (&ids[i], child_wait, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+ }
+
+ /* Wait for other threads to reach their wait func. */
+ while (true)
+ {
+ mtx_lock (&mutex);
+ TEST_VERIFY (waiting_threads <= N);
+ bool done_waiting = waiting_threads == N;
+ mtx_unlock (&mutex);
+ if (done_waiting)
+ break;
+ thrd_sleep (&((struct timespec){.tv_nsec = 100 * 1000 * 1000}), NULL);
+ }
+
+ mtx_lock (&mutex);
+ if (cnd_broadcast (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_broadcast failed");
+ mtx_unlock (&mutex);
+
+ for (i = 0; i < N; ++i)
+ {
+ if (thrd_join (ids[i], NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+ }
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-cnd-timedwait.c b/sysdeps/pthread/tst-cnd-timedwait.c
new file mode 100644
index 0000000000..05e3a051a5
--- /dev/null
+++ b/sysdeps/pthread/tst-cnd-timedwait.c
@@ -0,0 +1,84 @@
+/* C11 threads condition timed wait variable tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared condition variable between child and parent. */
+static cnd_t cond;
+
+/* Mutex needed to signal and wait threads. */
+static mtx_t mutex;
+
+static int
+signal_parent (void *arg)
+{
+ /* Acquire the lock so that cnd_signal does not run until
+ cnd_timedwait has been called. */
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+ if (cnd_signal (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_signal failed");
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ struct timespec w_time;
+
+ if (cnd_init (&cond) != thrd_success)
+ FAIL_EXIT1 ("cnd_init failed");
+ if (mtx_init (&mutex, mtx_plain) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ if (clock_gettime (CLOCK_REALTIME, &w_time) != 0)
+ FAIL_EXIT1 ("clock_gettime failed");
+
+ /* This needs to be sufficiently long to prevent the cnd_timedwait
+ call from timing out. */
+ w_time.tv_sec += 3600;
+
+ if (thrd_create (&id, signal_parent, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (cnd_timedwait (&cond, &mutex, &w_time) != thrd_success)
+ FAIL_EXIT1 ("cnd_timedwait failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock");
+
+ mtx_destroy (&mutex);
+ cnd_destroy (&cond);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-mtx-basic.c b/sysdeps/pthread/tst-mtx-basic.c
new file mode 100644
index 0000000000..1e3d809bd0
--- /dev/null
+++ b/sysdeps/pthread/tst-mtx-basic.c
@@ -0,0 +1,73 @@
+/* C11 threads basic mutex tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static int counter;
+
+static int
+child_add (void *arg)
+{
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ counter++;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ mtx_init (&mutex, mtx_plain);
+
+ thrd_t id;
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ counter++;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (counter != 2)
+ FAIL_EXIT1 ("counter (%d) != 2", counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-mtx-recursive.c b/sysdeps/pthread/tst-mtx-recursive.c
new file mode 100644
index 0000000000..6b471ac724
--- /dev/null
+++ b/sysdeps/pthread/tst-mtx-recursive.c
@@ -0,0 +1,45 @@
+/* C11 threads recursive mutex tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+ static mtx_t mutex;
+
+ if (mtx_init (&mutex, mtx_recursive) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ /* Lock mutex second time, if not recursive should deadlock. */
+ if (mtx_lock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_lock failed");
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-mtx-timedlock.c b/sysdeps/pthread/tst-mtx-timedlock.c
new file mode 100644
index 0000000000..21c73a3d60
--- /dev/null
+++ b/sysdeps/pthread/tst-mtx-timedlock.c
@@ -0,0 +1,103 @@
+/* C11 threads timed mutex tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static char shrd_counter;
+
+/* Maximum amount of time waiting for mutex. */
+static struct timespec wait_time;
+
+/* Function to choose an action to do, depending on mtx_timedlock
+ return value. */
+static inline void
+choose_action (int action, char* thread_name)
+{
+ switch (action)
+ {
+ case thrd_success:
+ ++shrd_counter;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+ break;
+
+ case thrd_timedout:
+ break;
+
+ case thrd_error:
+ FAIL_EXIT1 ("%s lock error", thread_name);
+ break;
+ }
+}
+
+static int
+child_add (void *arg)
+{
+ char child_name[] = "child";
+
+ /* Try to lock mutex. */
+ choose_action (mtx_timedlock (&mutex, &wait_time), child_name);
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ char parent_name[] = "parent";
+
+ if (mtx_init (&mutex, mtx_timed) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (clock_gettime (CLOCK_REALTIME, &wait_time) != 0)
+ FAIL_EXIT1 ("clock_gettime failed");
+ /* Tiny amount of time, to assure that if any thread finds it busy.
+ It will receive thrd_timedout. */
+ wait_time.tv_nsec += 1;
+ if (wait_time.tv_nsec == 1000 * 1000 * 1000)
+ {
+ wait_time.tv_sec += 1;
+ wait_time.tv_nsec = 0;
+ }
+
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ choose_action (mtx_timedlock (&mutex, &wait_time), parent_name);
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (shrd_counter != 2 && shrd_counter != 1)
+ FAIL_EXIT1 ("shrd_counter != {1,2} (%d)", shrd_counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-mtx-trylock.c b/sysdeps/pthread/tst-mtx-trylock.c
new file mode 100644
index 0000000000..dcb7a5407b
--- /dev/null
+++ b/sysdeps/pthread/tst-mtx-trylock.c
@@ -0,0 +1,90 @@
+/* C11 threads trylock mutex tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Shared mutex between child and parent. */
+static mtx_t mutex;
+
+/* Shared counter to check possible race conditions. */
+static char shrd_counter;
+
+/* Function to choose an action to do, depending on mtx_trylock
+ return value. */
+static inline void
+choose_action (int action, char* thread_name)
+{
+ switch (action)
+ {
+ case thrd_success:
+ ++shrd_counter;
+
+ if (mtx_unlock (&mutex) != thrd_success)
+ FAIL_EXIT1 ("mtx_unlock failed");
+ break;
+
+ case thrd_busy:
+ break;
+
+ case thrd_error:
+ FAIL_EXIT1 ("%s lock error", thread_name);
+ break;
+ }
+}
+
+static int
+child_add (void *arg)
+{
+ char child_name[] = "child";
+
+ /* Try to lock mutex. */
+ choose_action (mtx_trylock (&mutex), child_name);
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ char parent_name[] = "parent";
+
+ if (mtx_init (&mutex, mtx_timed) != thrd_success)
+ FAIL_EXIT1 ("mtx_init failed");
+
+ if (thrd_create (&id, child_add, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ choose_action (mtx_trylock (&mutex), parent_name);
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_join failed");
+
+ if (shrd_counter != 2 && shrd_counter != 1)
+ FAIL_EXIT1 ("shrd_counter != {1,2} (%d)", shrd_counter);
+
+ mtx_destroy (&mutex);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-thrd-detach.c b/sysdeps/pthread/tst-thrd-detach.c
new file mode 100644
index 0000000000..53be296f97
--- /dev/null
+++ b/sysdeps/pthread/tst-thrd-detach.c
@@ -0,0 +1,52 @@
+/* C11 threads thread detach tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+detach_thrd (void *arg)
+{
+ if (thrd_detach (thrd_current ()) != thrd_success)
+ FAIL_EXIT1 ("thrd_detach failed");
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+
+ /* Create new thread. */
+ if (thrd_create (&id, detach_thrd, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ /* Give some time so the thread can finish. */
+ thrd_sleep (&(struct timespec) {.tv_sec = 2}, NULL);
+
+ if (thrd_join (id, NULL) == thrd_success)
+ FAIL_EXIT1 ("thrd_join succeed where it should fail");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-thrd-sleep.c b/sysdeps/pthread/tst-thrd-sleep.c
new file mode 100644
index 0000000000..39d5fc7079
--- /dev/null
+++ b/sysdeps/pthread/tst-thrd-sleep.c
@@ -0,0 +1,51 @@
+/* C11 threads thread sleep tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+static int
+sleep_thrd (void *arg)
+{
+ struct timespec const *tl = (struct timespec const *) arg;
+ if (thrd_sleep (tl, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_sleep failed");
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ thrd_t id;
+ struct timespec wait_time = {.tv_sec = 3};
+
+ if (thrd_create (&id, sleep_thrd, (void *) (&wait_time)) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd failed");
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/pthread/tst-tss-basic.c b/sysdeps/pthread/tst-tss-basic.c
new file mode 100644
index 0000000000..3b06abc5cf
--- /dev/null
+++ b/sysdeps/pthread/tst-tss-basic.c
@@ -0,0 +1,75 @@
+/* C11 threads specific storage tests.
+ Copyright (C) 2018-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 <threads.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <support/check.h>
+
+/* Thread specific storage. */
+static tss_t key;
+
+#define TSS_VALUE (void*) 0xFF
+
+static int
+tss_thrd (void *arg)
+{
+ if (tss_create (&key, NULL) != thrd_success)
+ FAIL_EXIT1 ("tss_create failed");
+
+ if (tss_set (key, TSS_VALUE))
+ FAIL_EXIT1 ("tss_set failed");
+
+ void *value = tss_get (key);
+ if (value == 0)
+ FAIL_EXIT1 ("tss_get failed");
+ if (value != TSS_VALUE)
+ FAIL_EXIT1 ("tss_get returned %p, expected %p", value, TSS_VALUE);
+
+ thrd_exit (thrd_success);
+}
+
+static int
+do_test (void)
+{
+ /* Setting an invalid key should return an error. */
+ if (tss_set (key, TSS_VALUE) == thrd_success)
+ FAIL_EXIT1 ("tss_set succeed where it should have failed");
+
+ if (tss_create (&key, NULL) != thrd_success)
+ FAIL_EXIT1 ("tss_create failed");
+
+ thrd_t id;
+ if (thrd_create (&id, tss_thrd, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd_create failed");
+
+ if (thrd_join (id, NULL) != thrd_success)
+ FAIL_EXIT1 ("thrd failed");
+
+ /* The value set in tss_thrd should not be visible here. */
+ void *value = tss_get (key);
+ if (value != 0)
+ FAIL_EXIT1 ("tss_get succeed where it should have failed");
+
+ tss_delete (key);
+
+ return 0;
+}
+
+#include <support/test-driver.c>