about summary refs log tree commit diff
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.gz
glibc-b05de1040009d0d07a5a2e2765cffe554ffbe6ac.tar.xz
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>