libstdc++: Add C++2a synchronization support

Message ID 20201026214827.3530995-1-rodgert@appliantology.com
State New
Headers show
Series
  • libstdc++: Add C++2a synchronization support
Related show

Commit Message

Thomas Rodgers Oct. 26, 2020, 9:48 p.m.
From: Thomas Rodgers <trodgers@redhat.com>


Add support for -
  * atomic_flag::wait/notify_one/notify_all
  * atomic::wait/notify_one/notify_all
  * counting_semaphore
  * binary_semaphore
  * latch

libstdc++-v3/ChangeLog:

	* include/Makefile.am (bits_headers): Add new header.
	* include/Makefile.in: Regenerate.
	* include/bits/atomic_base.h (__atomic_flag::wait): Define.
	(__atomic_flag::notify_one): Likewise.
	(__atomic_flag::notify_all): Likewise.
	(__atomic_base<_Itp>::wait): Likewise.
	(__atomic_base<_Itp>::notify_one): Likewise.
	(__atomic_base<_Itp>::notify_all): Likewise.
	(__atomic_base<_Ptp*>::wait): Likewise.
	(__atomic_base<_Ptp*>::notify_one): Likewise.
	(__atomic_base<_Ptp*>::notify_all): Likewise.
	(__atomic_impl::wait): Likewise.
	(__atomic_impl::notify_one): Likewise.
	(__atomic_impl::notify_all): Likewise.
	(__atomic_float<_Fp>::wait): Likewise.
	(__atomic_float<_Fp>::notify_one): Likewise.
	(__atomic_float<_Fp>::notify_all): Likewise.
	(__atomic_ref<_Tp>::wait): Likewise.
	(__atomic_ref<_Tp>::notify_one): Likewise.
	(__atomic_ref<_Tp>::notify_all): Likewise.
	(atomic_wait<_Tp>): Likewise.
	(atomic_wait_explicit<_Tp>): Likewise.
	(atomic_notify_one<_Tp>): Likewise.
	(atomic_notify_all<_Tp>): Likewise.
	* include/bits/atomic_wait.h: New file.
	* include/bits/atomic_timed_wait.h: New file.
	* include/bits/semaphore_base.h: New file.
	* include/std/atomic (atomic<bool>::wait): Define.
	(atomic<bool>::wait_one): Likewise.
	(atomic<bool>::wait_all): Likewise.
	(atomic<_Tp>::wait): Likewise.
	(atomic<_Tp>::wait_one): Likewise.
	(atomic<_Tp>::wait_all): Likewise.
	(atomic<_Tp*>::wait): Likewise.
	(atomic<_Tp*>::wait_one): Likewise.
	(atomic<_Tp*>::wait_all): Likewise.
	* include/std/latch: New file.
	* include/std/semaphore: New file.
	* include/std/version: Add __cpp_lib_semaphore and
	__cpp_lib_latch defines.
	* testsuite/29_atomic/atomic/wait_notify/bool.cc: New test.
	* testsuite/29_atomic/atomic/wait_notify/pointers.cc: Likewise.
	* testsuite/29_atomic/atomic/wait_notify/generic.cc: Liekwise.
	* testsuite/29_atomics/atomic_flag/wait_notify/1.cc: Likewise.
	* testsuite/29_atomic/atomic_float/wait_notify.cc: Likewise.
	* testsuite/29_atomic/atomic_integral/wait_notify.cc: Likewise.
	* testsuite/29_atomic/atomic_ref/wait_notify.cc: Likewise.
	* testsuite/30_thread/semaphore/1.cc: New test.
	* testsuite/30_thread/semaphore/2.cc: Likewise.
	* testsuite/30_thread/semaphore/least_max_value_neg.cc: Likewise.
	* testsuite/30_thread/semaphore/try_acquire.cc: Likewise.
	* testsuite/30_thread/semaphore/try_acquire_for.cc: Likewise.
	* testsuite/30_thread/semaphore/try_acquire_posix.cc: Likewise.
	* testsuite/30_thread/semaphore/try_acquire_until.cc: Likewise.
	* testsuite/30_thread/latch/1.cc: New test.
	* testsuite/30_thread/latch/2.cc: New test.
	* testsuite/30_thread/latch/3.cc: New test.
	* testsuite/util/atomic/wait_notify_util.h: New File.
---
 libstdc++-v3/include/Makefile.am              |   5 +
 libstdc++-v3/include/Makefile.in              |   5 +
 libstdc++-v3/include/bits/atomic_base.h       | 195 ++++++++++-
 libstdc++-v3/include/bits/atomic_timed_wait.h | 287 ++++++++++++++++
 libstdc++-v3/include/bits/atomic_wait.h       | 306 ++++++++++++++++++
 libstdc++-v3/include/bits/semaphore_base.h    | 296 +++++++++++++++++
 libstdc++-v3/include/std/atomic               |  78 +++++
 libstdc++-v3/include/std/latch                |  91 ++++++
 libstdc++-v3/include/std/semaphore            |  92 ++++++
 libstdc++-v3/include/std/version              |   2 +
 .../29_atomics/atomic/wait_notify/bool.cc     |  59 ++++
 .../29_atomics/atomic/wait_notify/generic.cc  |  31 ++
 .../29_atomics/atomic/wait_notify/pointers.cc |  59 ++++
 .../29_atomics/atomic_flag/wait_notify/1.cc   |  61 ++++
 .../29_atomics/atomic_float/wait_notify.cc    |  32 ++
 .../29_atomics/atomic_integral/wait_notify.cc |  65 ++++
 .../29_atomics/atomic_ref/wait_notify.cc      | 103 ++++++
 libstdc++-v3/testsuite/30_threads/latch/1.cc  |  27 ++
 libstdc++-v3/testsuite/30_threads/latch/2.cc  |  27 ++
 libstdc++-v3/testsuite/30_threads/latch/3.cc  |  69 ++++
 .../testsuite/30_threads/semaphore/1.cc       |  27 ++
 .../testsuite/30_threads/semaphore/2.cc       |  27 ++
 .../semaphore/least_max_value_neg.cc          |  30 ++
 .../30_threads/semaphore/try_acquire.cc       |  55 ++++
 .../30_threads/semaphore/try_acquire_for.cc   |  85 +++++
 .../30_threads/semaphore/try_acquire_posix.cc | 153 +++++++++
 .../30_threads/semaphore/try_acquire_until.cc |  94 ++++++
 .../testsuite/util/atomic/wait_notify_util.h  | 160 +++++++++
 28 files changed, 2520 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/include/bits/atomic_timed_wait.h
 create mode 100644 libstdc++-v3/include/bits/atomic_wait.h
 create mode 100644 libstdc++-v3/include/bits/semaphore_base.h
 create mode 100644 libstdc++-v3/include/std/latch
 create mode 100644 libstdc++-v3/include/std/semaphore
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
 create mode 100644 libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/latch/1.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/latch/2.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/latch/3.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/1.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/2.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
 create mode 100644 libstdc++-v3/testsuite/util/atomic/wait_notify_util.h

-- 
2.26.2

Comments

Jeff Law via Gcc-patches Oct. 27, 2020, 10:23 a.m. | #1
On 26/10/20 14:48 -0700, Thomas Rodgers wrote:
>+#include <ext/numeric_traits.h>

>+

>+#if __has_include(<semaphore.h>)

>+#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1

>+#include <semaphore.h>


It occurs to me now that this check probably isn't robust enough. For
any POSIX system it's probably safe to assume that <semaphore.h> means
the POSIX header and so sem_t is available.

But on non-POSIX systems there could be some other, unrelated header
called <semaphore.h> in the include paths that the user is compiling
this header with. It's not inconceivable that the user's own project
or some third party lib could provide a file called semaphore.h, which
wouldn't define sem_t, sem_init etc.

It's OK for now, but we should revisit this and add an autoconf check
for sem_init etc. to check at build time whether we've got POSIX
semaphores available or not.

Please add a "FIXME: replace this with an autoconf check" comment
here.

OK for trunk with that change, thanks.
Thomas Rodgers Nov. 20, 2020, 10:44 p.m. | #2
Tested x86_64-pc-linux-gnu, committed.

> On Oct 27, 2020, at 3:23 AM, Jonathan Wakely <jwakely@redhat.com> wrote:

> 

> On 26/10/20 14:48 -0700, Thomas Rodgers wrote:

>> +#include <ext/numeric_traits.h>

>> +

>> +#if __has_include(<semaphore.h>)

>> +#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1

>> +#include <semaphore.h>

> 

> It occurs to me now that this check probably isn't robust enough. For

> any POSIX system it's probably safe to assume that <semaphore.h> means

> the POSIX header and so sem_t is available.

> 

> But on non-POSIX systems there could be some other, unrelated header

> called <semaphore.h> in the include paths that the user is compiling

> this header with. It's not inconceivable that the user's own project

> or some third party lib could provide a file called semaphore.h, which

> wouldn't define sem_t, sem_init etc.

> 

> It's OK for now, but we should revisit this and add an autoconf check

> for sem_init etc. to check at build time whether we've got POSIX

> semaphores available or not.

> 

> Please add a "FIXME: replace this with an autoconf check" comment

> here.

> 

> OK for trunk with that change, thanks.

>
Andreas Schwab Nov. 21, 2020, 3:16 p.m. | #3
In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,
                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:
/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':
/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'
In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,
                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:
/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'
/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:
In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,
                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,
                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:
/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."
Jeff Law via Gcc-patches Nov. 21, 2020, 5:04 p.m. | #4
On 21/11/20 16:16 +0100, Andreas Schwab wrote:
>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>                 from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>                 from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')


I'm testing this.
commit 613ac97bed57eb0edb1803b66d5ce3510e665b3d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Sat Nov 21 16:52:22 2020

    libstdc++: Fix atomic waiting for non-linux targets
    
    This fixes some UNRESOLVED tests on (at least) Solaris and Darwin, and
    disables some tests that hang forever on Solaris. A proper fix is still
    needed.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/atomic_base.h (atomic_flag::wait): Use correct
            type for __atomic_wait call.
            * include/bits/atomic_timed_wait.h (__atomic_wait_until): Check
            _GLIBCXX_HAVE_LINUX_FUTEX.
            * include/bits/atomic_wait.h (__atomic_notify): Likewise.
            * include/bits/semaphore_base.h (_GLIBCXX_HAVE_POSIX_SEMAPHORE):
            Only define if SEM_VALUE_MAX or _POSIX_SEM_VALUE_MAX is defined.
            * testsuite/29_atomics/atomic/wait_notify/bool.cc: Disable on
            non-linux targes.
            * testsuite/29_atomics/atomic/wait_notify/pointers.cc: Likewise.
            * testsuite/29_atomics/atomic_flag/wait_notify/1.cc: Likewise.
            * testsuite/29_atomics/atomic_float/wait_notify.cc: Likewise.

diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index dd4db926592e..7de02f169977 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -234,7 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     wait(bool __old,
 	memory_order __m = memory_order_seq_cst) const noexcept
     {
-      std::__atomic_wait(&_M_i, __old,
+      std::__atomic_wait(&_M_i, static_cast<__atomic_flag_data_type>(__old),
 			 [__m, this, __old]()
 			 { return this->test(__m) != __old; });
     }
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 7712a6c591dc..405f7e93ca85 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -240,12 +240,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       do
 	{
 	  __atomic_wait_status __res;
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
 	  if constexpr (__platform_wait_uses_type<_Tp>)
 	    {
 	      __res = __detail::__platform_wait_until((__platform_wait_t*)(void*) __addr,
 						      __old, __atime);
 	    }
 	  else
+#endif
 	    {
 	      __res = __w._M_do_wait_until(__version, __atime);
 	    }
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index 2d08e5325fb2..7b2682a577ef 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -292,11 +292,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (!__w._M_waiting())
 	return;
 
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
       if constexpr (__platform_wait_uses_type<_Tp>)
 	{
 	  __platform_notify((__platform_wait_t*)(void*) __addr, __all);
 	}
       else
+#endif
 	{
 	  __w._M_notify(__all);
 	}
diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
index da6dc4b91858..78a0b6ba26e6 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -39,8 +39,10 @@
 #include <ext/numeric_traits.h>
 
 #if __has_include(<semaphore.h>)
-#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
-#include <semaphore.h>
+# include <semaphore.h>
+# if defined SEM_VALUE_MAX || _POSIX_SEM_VALUE_MAX
+#  define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
+# endif
 #endif
 
 #include <chrono>
@@ -54,7 +56,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __platform_semaphore
   {
     using __clock_t = chrono::system_clock;
+#ifdef SEM_VALUE_MAX
     static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
+#else
+    static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
+#endif
 
     explicit __platform_semaphore(ptrdiff_t __count) noexcept
     {
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
index 5f1e30a710fe..29781c6e1357 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
index 8531bb2e7880..f54961f893d4 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
+// { dg-additional-options "-pthread" { target pthread } }
 // { dg-require-gthreads "" }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
index 4f026e1dc9c1..763d3e77159c 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
index 640a84e0342e..27d9b601c2f4 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
Jeff Law via Gcc-patches Nov. 21, 2020, 5:39 p.m. | #5
On 21/11/20 17:04 +0000, Jonathan Wakely wrote:
>On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>

>I'm testing this.


I'm committing this instead, it's the same but also disables
29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

Tested sparc-solaris2.11 and powerpc64le-linux.

There are still some timeouts on linux:

FAIL: 30_threads/latch/3.cc execution test
FAIL: 30_threads/semaphore/try_acquire_for.cc execution test
commit 6f5387b7c9047baa5ee1385c8f5148d2c351bd20
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Sat Nov 21 16:52:22 2020

    libstdc++: Fix atomic waiting for non-linux targets
    
    This fixes some UNRESOLVED tests on (at least) Solaris and Darwin, and
    disables some tests that hang forever on Solaris. A proper fix is still
    needed.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/atomic_base.h (atomic_flag::wait): Use correct
            type for __atomic_wait call.
            * include/bits/atomic_timed_wait.h (__atomic_wait_until): Check
            _GLIBCXX_HAVE_LINUX_FUTEX.
            * include/bits/atomic_wait.h (__atomic_notify): Likewise.
            * include/bits/semaphore_base.h (_GLIBCXX_HAVE_POSIX_SEMAPHORE):
            Only define if SEM_VALUE_MAX or _POSIX_SEM_VALUE_MAX is defined.
            * testsuite/29_atomics/atomic/wait_notify/bool.cc: Disable on
            non-linux targes.
            * testsuite/29_atomics/atomic/wait_notify/generic.cc: Likewise.
            * testsuite/29_atomics/atomic/wait_notify/pointers.cc: Likewise.
            * testsuite/29_atomics/atomic_flag/wait_notify/1.cc: Likewise.
            * testsuite/29_atomics/atomic_float/wait_notify.cc: Likewise.

diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index dd4db926592e..7de02f169977 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -234,7 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     wait(bool __old,
 	memory_order __m = memory_order_seq_cst) const noexcept
     {
-      std::__atomic_wait(&_M_i, __old,
+      std::__atomic_wait(&_M_i, static_cast<__atomic_flag_data_type>(__old),
 			 [__m, this, __old]()
 			 { return this->test(__m) != __old; });
     }
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
index 7712a6c591dc..405f7e93ca85 100644
--- a/libstdc++-v3/include/bits/atomic_timed_wait.h
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -240,12 +240,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       do
 	{
 	  __atomic_wait_status __res;
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
 	  if constexpr (__platform_wait_uses_type<_Tp>)
 	    {
 	      __res = __detail::__platform_wait_until((__platform_wait_t*)(void*) __addr,
 						      __old, __atime);
 	    }
 	  else
+#endif
 	    {
 	      __res = __w._M_do_wait_until(__version, __atime);
 	    }
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index 2d08e5325fb2..7b2682a577ef 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -292,11 +292,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       if (!__w._M_waiting())
 	return;
 
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
       if constexpr (__platform_wait_uses_type<_Tp>)
 	{
 	  __platform_notify((__platform_wait_t*)(void*) __addr, __all);
 	}
       else
+#endif
 	{
 	  __w._M_notify(__all);
 	}
diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
index da6dc4b91858..78a0b6ba26e6 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -39,8 +39,10 @@
 #include <ext/numeric_traits.h>
 
 #if __has_include(<semaphore.h>)
-#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
-#include <semaphore.h>
+# include <semaphore.h>
+# if defined SEM_VALUE_MAX || _POSIX_SEM_VALUE_MAX
+#  define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
+# endif
 #endif
 
 #include <chrono>
@@ -54,7 +56,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __platform_semaphore
   {
     using __clock_t = chrono::system_clock;
+#ifdef SEM_VALUE_MAX
     static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
+#else
+    static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX;
+#endif
 
     explicit __platform_semaphore(ptrdiff_t __count) noexcept
     {
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
index 5f1e30a710fe..29781c6e1357 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
index 0249341055cc..629556a9d2d0 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
index 8531bb2e7880..f54961f893d4 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
+// { dg-additional-options "-pthread" { target pthread } }
 // { dg-require-gthreads "" }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
index 4f026e1dc9c1..763d3e77159c 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
index 640a84e0342e..27d9b601c2f4 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
@@ -1,7 +1,8 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
Jeff Law via Gcc-patches Nov. 22, 2020, 12:36 a.m. | #6
On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>

> On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

> >On 21/11/20 16:16 +0100, Andreas Schwab wrote:

> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

> >

> >I'm testing this.

>

> I'm committing this instead, it's the same but also disables

> 29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>

> Tested sparc-solaris2.11 and powerpc64le-linux.

>

> There are still some timeouts on linux:

>

> FAIL: 30_threads/latch/3.cc execution test

> FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>


I opened:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936

-- 
H.J.
Jeff Law via Gcc-patches Nov. 22, 2020, 9:13 p.m. | #7
On 20/11/2020 23:44, Thomas Rodgers wrote:
> Tested x86_64-pc-linux-gnu, committed.


Clang complains:

> $ cat test.cc

> #include <semaphore>

> 

> $ clang++ --gcc-toolchain=~/gcc/trunk/inst -std=c++20 -fsyntax-only test.cc

> In file included from test.cc:1:

> In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/semaphore:36:

> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/semaphore_base.h:145:22: error: no viable conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'const std::__platform_semaphore::__clock_t' (aka 'const std::chrono::system_clock')

>             const __clock_t __s_entry = __clock_t::now();

>                             ^           ~~~~~~~~~~~~~~~~

> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/chrono:1101:12: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'const std::chrono::system_clock &' for 1st argument

>     struct system_clock

>            ^

> ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/chrono:1101:12: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'std::chrono::system_clock &&' for 1st argument

> 1 error generated.


which

> diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h

> index 78a0b6ba26e..f25c9fdb325 100644

> --- a/libstdc++-v3/include/bits/semaphore_base.h

> +++ b/libstdc++-v3/include/bits/semaphore_base.h

> @@ -142,7 +142,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>         else

>           {

>             const typename _Clock::time_point __c_entry = _Clock::now();

> -           const __clock_t __s_entry = __clock_t::now();

> +           const __clock_t::time_point __s_entry = __clock_t::now();

>             const auto __delta = __atime - __c_entry;

>             const auto __s_atime = __s_entry + __delta;

>             if (_M_try_acquire_until_impl(__s_atime))

> ~


would fix.
Jeff Law via Gcc-patches Nov. 22, 2020, 9:41 p.m. | #8
On 20/11/2020 23:44, Thomas Rodgers wrote:
> Tested x86_64-pc-linux-gnu, committed.


...and there are multiple definition complaints from the linker because 
of two missing "include":

> index 7b2682a577e..23ab2018ca8 100644

> --- a/libstdc++-v3/include/bits/atomic_wait.h

> +++ b/libstdc++-v3/include/bits/atomic_wait.h

> @@ -223,7 +223,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>        { _M_w._M_do_wait(_M_version); }

>      };

>  

> -    void

> +    inline void

>      __thread_relax() noexcept

>      {

>  #if defined __i386__ || defined __x86_64__

> @@ -233,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>  #endif

>      }

>  

> -    void

> +    inline void

>      __thread_yield() noexcept

>     {

>  #if defined _GLIBCXX_USE_SCHED_YIELD
Jeff Law via Gcc-patches Nov. 23, 2020, 2:50 p.m. | #9
On 21/11/20 16:36 -0800, H.J. Lu wrote:
>On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches

><gcc-patches@gcc.gnu.org> wrote:

>>

>> On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>> >On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>> >

>> >I'm testing this.

>>

>> I'm committing this instead, it's the same but also disables

>> 29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>>

>> Tested sparc-solaris2.11 and powerpc64le-linux.

>>

>> There are still some timeouts on linux:

>>

>> FAIL: 30_threads/latch/3.cc execution test

>> FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>>

>

>I opened:

>

>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936


Thanks.
Jeff Law via Gcc-patches Nov. 23, 2020, 4:08 p.m. | #10
On 21/11/20 17:39 +0000, Jonathan Wakely wrote:
>On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>>On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>>

>>I'm testing this.

>

>I'm committing this instead, it's the same but also disables

>29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>

>Tested sparc-solaris2.11 and powerpc64le-linux.

>

>There are still some timeouts on linux:

>

>FAIL: 30_threads/latch/3.cc execution test

>FAIL: 30_threads/semaphore/try_acquire_for.cc execution test



Here's another small fix.

Tested powerpc64le-linux, pushed to trunk.
commit fd62daea40e09c1e6d599a6171db6b298d6c362e
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Nov 23 15:46:24 2020

    libstdc++: Link tests to libatomic as required [PR 97948]
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/97948
            * testsuite/29_atomics/atomic_float/wait_notify.cc: Add options
            for libatomic.
            * testsuite/29_atomics/atomic_integral/wait_notify.cc: Likewise.
            * testsuite/29_atomics/atomic_ref/wait_notify.cc: Likewise.

diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
index 27d9b601c2f4..8f9e4a39a21f 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
@@ -2,6 +2,7 @@
 // { dg-do run { target c++2a } }
 // { dg-require-gthreads "" }
 // { dg-additional-options "-pthread" { target pthread } }
+// { dg-add-options libatomic }
 // { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
index 6e9ee7dbf93f..abf2bfdbee96 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
@@ -2,6 +2,7 @@
 // { dg-do run { target c++2a } }
 // { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-add-options libatomic }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
index dc5ae7a21eac..b38fc206d468 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
@@ -2,6 +2,7 @@
 // { dg-do run { target c++2a } }
 // { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-add-options libatomic }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
Jeff Law via Gcc-patches Nov. 23, 2020, 6:32 p.m. | #11
On 22/11/20 22:41 +0100, Stephan Bergmann wrote:
>On 20/11/2020 23:44, Thomas Rodgers wrote:

>>Tested x86_64-pc-linux-gnu, committed.

>

>...and there are multiple definition complaints from the linker 

>because of two missing "include":

>

>>index 7b2682a577e..23ab2018ca8 100644

>>--- a/libstdc++-v3/include/bits/atomic_wait.h

>>+++ b/libstdc++-v3/include/bits/atomic_wait.h

>>@@ -223,7 +223,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>>       { _M_w._M_do_wait(_M_version); }

>>     };

>>-    void

>>+    inline void

>>     __thread_relax() noexcept

>>     {

>> #if defined __i386__ || defined __x86_64__

>>@@ -233,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>> #endif

>>     }

>>-    void

>>+    inline void

>>     __thread_yield() noexcept

>>    {

>> #if defined _GLIBCXX_USE_SCHED_YIELD


Committed, thanks.
commit 0986d3bc621b12c3d0367bf7bd25927c7fbfc552
Author: Stephan Bergmann <sbergman@redhat.com>
Date:   Mon Nov 23 18:14:44 2020

    libstdc++: Fix linker errors due to missing 'inline' keywords
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/atomic_wait.h (__thread_relax, __thread_yield):
            Add 'inline'.

diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index a40cff124d7d..cd756f68de6d 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -224,7 +224,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { _M_w._M_do_wait(_M_version); }
     };
 
-    void
+    inline void
     __thread_relax() noexcept
     {
 #if defined __i386__ || defined __x86_64__
@@ -234,9 +234,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
     }
 
-    void
+    inline void
     __thread_yield() noexcept
-   {
+    {
 #if defined _GLIBCXX_USE_SCHED_YIELD
      __gthread_yield();
 #endif
Jeff Law via Gcc-patches Nov. 23, 2020, 6:33 p.m. | #12
On 22/11/20 22:13 +0100, Stephan Bergmann wrote:
>On 20/11/2020 23:44, Thomas Rodgers wrote:

>>Tested x86_64-pc-linux-gnu, committed.

>

>Clang complains:

>

>>$ cat test.cc

>>#include <semaphore>

>>

>>$ clang++ --gcc-toolchain=~/gcc/trunk/inst -std=c++20 -fsyntax-only test.cc

>>In file included from test.cc:1:

>>In file included from ~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/semaphore:36:

>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/bits/semaphore_base.h:145:22: error: no viable conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'const std::__platform_semaphore::__clock_t' (aka 'const std::chrono::system_clock')

>>            const __clock_t __s_entry = __clock_t::now();

>>                            ^           ~~~~~~~~~~~~~~~~

>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/chrono:1101:12: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'const std::chrono::system_clock &' for 1st argument

>>    struct system_clock

>>           ^

>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/11.0.0/../../../../include/c++/11.0.0/chrono:1101:12: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'std::chrono::system_clock::time_point' (aka 'time_point<std::chrono::system_clock, duration<long, ratio<1, 1000000000>>>') to 'std::chrono::system_clock &&' for 1st argument

>>1 error generated.

>

>which

>

>>diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h

>>index 78a0b6ba26e..f25c9fdb325 100644

>>--- a/libstdc++-v3/include/bits/semaphore_base.h

>>+++ b/libstdc++-v3/include/bits/semaphore_base.h

>>@@ -142,7 +142,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>>        else

>>          {

>>            const typename _Clock::time_point __c_entry = _Clock::now();

>>-           const __clock_t __s_entry = __clock_t::now();

>>+           const __clock_t::time_point __s_entry = __clock_t::now();

>>            const auto __delta = __atime - __c_entry;

>>            const auto __s_atime = __s_entry + __delta;

>>            if (_M_try_acquire_until_impl(__s_atime))

>>~

>

>would fix.


I just used 'auto'` instead.

Committed, thanks.

The fact this didn't error with GCC suggests we're missing some tests.
commit 1ccee0fbfa8e528b3671dfbf4dad5b6f67755e4c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Nov 23 18:16:44 2020

    libstdc++: Fix variable declared with wrong type
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/semaphore_base.h
            (__platform_semaphore::_M_try_acquire_until): Fix type of
            variable.

diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
index 0692f95f24f2..56333bbbfef7 100644
--- a/libstdc++-v3/include/bits/semaphore_base.h
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -141,7 +141,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	else
 	  {
 	    const typename _Clock::time_point __c_entry = _Clock::now();
-	    const __clock_t __s_entry = __clock_t::now();
+	    const auto __s_entry = __clock_t::now();
 	    const auto __delta = __atime - __c_entry;
 	    const auto __s_atime = __s_entry + __delta;
 	    if (_M_try_acquire_until_impl(__s_atime))
Jeff Law via Gcc-patches Nov. 24, 2020, 11:45 p.m. | #13
On 21/11/20 16:36 -0800, H.J. Lu wrote:
>On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches

><gcc-patches@gcc.gnu.org> wrote:

>>

>> On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>> >On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>> >>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>> >>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>> >>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>> >>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>> >

>> >I'm testing this.

>>

>> I'm committing this instead, it's the same but also disables

>> 29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>>

>> Tested sparc-solaris2.11 and powerpc64le-linux.

>>

>> There are still some timeouts on linux:

>>

>> FAIL: 30_threads/latch/3.cc execution test

>> FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>>

>

>I opened:

>

>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936


I've disabled the failing tests for now. They can be re-enabled after
the problem is found and fixed.

Committed to trunk.
commit a3313a2214a6253672ab4fa37a2dcf57fd0f8dce
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Nov 24 23:22:01 2020

    libstdc++: Disable failing tests [PR 97936]
    
    These tests are unstable and causing failures due to timeouts. Disable
    them until the cause can be found, so that testing doesn't have to wait
    for them to timeout.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/97936
            PR libstdc++/97944
            * testsuite/29_atomics/atomic_integral/wait_notify.cc: Disable.
            Do not require pthreads, but add -pthread when appropriate.
            * testsuite/30_threads/jthread/95989.cc: Likewise.
            * testsuite/30_threads/latch/3.cc: Likewise.
            * testsuite/30_threads/semaphore/try_acquire_until.cc: Likewise.

diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
index abf2bfdbee96..762583cf8c76 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
@@ -1,8 +1,9 @@
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
 // { dg-add-options libatomic }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { *-*-* } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/30_threads/jthread/95989.cc b/libstdc++-v3/testsuite/30_threads/jthread/95989.cc
index c7a9430eee90..a179eab38198 100644
--- a/libstdc++-v3/testsuite/30_threads/jthread/95989.cc
+++ b/libstdc++-v3/testsuite/30_threads/jthread/95989.cc
@@ -20,6 +20,7 @@
 // { dg-require-gthreads {} }
 // { dg-additional-options "-pthread" { target pthread } }
 // { dg-additional-options "-static" { target static } }
+// { dg-skip-if "broken" { *-*-* } }
 
 #include <thread>
 
diff --git a/libstdc++-v3/testsuite/30_threads/latch/3.cc b/libstdc++-v3/testsuite/30_threads/latch/3.cc
index 5d08000f4302..6304135a877c 100644
--- a/libstdc++-v3/testsuite/30_threads/latch/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/latch/3.cc
@@ -15,11 +15,12 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
-//
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { *-*-* } }
+
 #include <latch>
 #include <atomic>
 #include <thread>
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
index af7ab7bac395..5e1141425f72 100644
--- a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
@@ -15,10 +15,11 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-options "-std=gnu++2a -pthread" }
+// { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
-// { dg-require-effective-target pthread }
 // { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-skip-if "broken" { *-*-* } }
 
 #include <semaphore>
 #include <chrono>
Jeff Law via Gcc-patches Nov. 25, 2020, 1:07 a.m. | #14
On 24/11/20 23:45 +0000, Jonathan Wakely wrote:
>On 21/11/20 16:36 -0800, H.J. Lu wrote:

>>On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches

>><gcc-patches@gcc.gnu.org> wrote:

>>>

>>>On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>>>>On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>                from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>                from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>>>>

>>>>I'm testing this.

>>>

>>>I'm committing this instead, it's the same but also disables

>>>29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>>>

>>>Tested sparc-solaris2.11 and powerpc64le-linux.

>>>

>>>There are still some timeouts on linux:

>>>

>>>FAIL: 30_threads/latch/3.cc execution test

>>>FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>>>

>>

>>I opened:

>>

>>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936

>

>I've disabled the failing tests for now. They can be re-enabled after

>the problem is found and fixed.


I was finally able to reproduce the hangs, and I think this is the
fix:

--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -100,9 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
             auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),
                                   static_cast<int>(__futex_wait_flags::__wait_private),
                                     __val, nullptr);
-           if (!__e)
+           if (!__e || errno == EAGAIN)
               break;
-           else if (!(errno == EINTR || errno == EAGAIN))
+           else if (errno != EINTR)
               __throw_system_error(__e);
           }
        }

The problem is that we're going into a busy loop when SYS_futex
returns EAGAIN, but that means the current value doesn't match the
expected value, so we should return not keep waiting for the value to
change.
Jeff Law via Gcc-patches Nov. 25, 2020, 10:35 a.m. | #15
On 25/11/20 01:07 +0000, Jonathan Wakely wrote:
>On 24/11/20 23:45 +0000, Jonathan Wakely wrote:

>>On 21/11/20 16:36 -0800, H.J. Lu wrote:

>>>On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches

>>><gcc-patches@gcc.gnu.org> wrote:

>>>>

>>>>On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>>>>>On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>               from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>>>>>

>>>>>I'm testing this.

>>>>

>>>>I'm committing this instead, it's the same but also disables

>>>>29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>>>>

>>>>Tested sparc-solaris2.11 and powerpc64le-linux.

>>>>

>>>>There are still some timeouts on linux:

>>>>

>>>>FAIL: 30_threads/latch/3.cc execution test

>>>>FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>>>>

>>>

>>>I opened:

>>>

>>>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936

>>

>>I've disabled the failing tests for now. They can be re-enabled after

>>the problem is found and fixed.

>

>I was finally able to reproduce the hangs, and I think this is the

>fix:

>

>--- a/libstdc++-v3/include/bits/atomic_wait.h

>+++ b/libstdc++-v3/include/bits/atomic_wait.h

>@@ -100,9 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>            auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),

>                                  static_cast<int>(__futex_wait_flags::__wait_private),

>                                    __val, nullptr);

>-           if (!__e)

>+           if (!__e || errno == EAGAIN)

>              break;

>-           else if (!(errno == EINTR || errno == EAGAIN))

>+           else if (errno != EINTR)

>              __throw_system_error(__e);

>          }

>       }

>

>The problem is that we're going into a busy loop when SYS_futex

>returns EAGAIN, but that means the current value doesn't match the

>expected value, so we should return not keep waiting for the value to

>change.


I've pushed that as ad9cbcee543ecccd79fa49dafcd925532d2ce210 but there
are still other FAILs to be fixed.
Jeff Law via Gcc-patches Nov. 25, 2020, 12:32 p.m. | #16
On 25/11/20 10:35 +0000, Jonathan Wakely wrote:
>On 25/11/20 01:07 +0000, Jonathan Wakely wrote:

>>On 24/11/20 23:45 +0000, Jonathan Wakely wrote:

>>>On 21/11/20 16:36 -0800, H.J. Lu wrote:

>>>>On Sat, Nov 21, 2020 at 9:40 AM Jonathan Wakely via Gcc-patches

>>>><gcc-patches@gcc.gnu.org> wrote:

>>>>>

>>>>>On 21/11/20 17:04 +0000, Jonathan Wakely wrote:

>>>>>>On 21/11/20 16:16 +0100, Andreas Schwab wrote:

>>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h: In member function 'void std::atomic_flag::wait(bool, std::memory_order) const':

>>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: error: no matching function for call to '__atomic_wait(const __atomic_flag_data_type*, bool&, std::atomic_flag::wait(bool, std::memory_order) const::<lambda()>)'

>>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:41,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note: candidate: 'template<class _Tp, class _Pred> void std::__atomic_wait(const _Tp*, _Tp, _Pred)'

>>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_wait.h:265: note:   template argument deduction/substitution failed:

>>>>>>>In file included from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/shared_ptr_atomic.h:33,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/memory:78,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/stdc++.h:82,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/m68k-linux/bits/extc++.h:32,

>>>>>>>              from /daten/aranym/gcc/gcc-20201121/libstdc++-v3/testsuite/17_intro/headers/c++2020/all_attributes.cc:37:

>>>>>>>/daten/aranym/gcc/gcc-20201121/Build/m68k-linux/libstdc++-v3/include/bits/atomic_base.h:239: note:   deduced conflicting types for parameter '_Tp' ('unsigned char' and 'bool')

>>>>>>

>>>>>>I'm testing this.

>>>>>

>>>>>I'm committing this instead, it's the same but also disables

>>>>>29_atomics/atomic/wait_notify/generic.cc on non-linux targets.

>>>>>

>>>>>Tested sparc-solaris2.11 and powerpc64le-linux.

>>>>>

>>>>>There are still some timeouts on linux:

>>>>>

>>>>>FAIL: 30_threads/latch/3.cc execution test

>>>>>FAIL: 30_threads/semaphore/try_acquire_for.cc execution test

>>>>>

>>>>

>>>>I opened:

>>>>

>>>>https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97936

>>>

>>>I've disabled the failing tests for now. They can be re-enabled after

>>>the problem is found and fixed.

>>

>>I was finally able to reproduce the hangs, and I think this is the

>>fix:

>>

>>--- a/libstdc++-v3/include/bits/atomic_wait.h

>>+++ b/libstdc++-v3/include/bits/atomic_wait.h

>>@@ -100,9 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

>>           auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),

>>                                 static_cast<int>(__futex_wait_flags::__wait_private),

>>                                   __val, nullptr);

>>-           if (!__e)

>>+           if (!__e || errno == EAGAIN)

>>             break;

>>-           else if (!(errno == EINTR || errno == EAGAIN))

>>+           else if (errno != EINTR)

>>             __throw_system_error(__e);

>>         }

>>      }

>>

>>The problem is that we're going into a busy loop when SYS_futex

>>returns EAGAIN, but that means the current value doesn't match the

>>expected value, so we should return not keep waiting for the value to

>>change.

>

>I've pushed that as ad9cbcee543ecccd79fa49dafcd925532d2ce210 but there

>are still other FAILs to be fixed.


Except that what I pushed was not what I wrote above, as noticed by
Jakub. I need to get more sleep.

Fixed with this patch, pushed to trunk.
commit a5ccfd04605d940daded7e95474389f1c7dfad61
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Nov 25 12:16:07 2020

    libstdc++: Fix silly typos [PR 97936]
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/97936
            * include/bits/atomic_wait.h (__platform_wait): Check errno,
            not just the value of EAGAIN.
            (__waiters::__waiters()): Fix name of data member.

diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
index fdf7c4586f22..5af9367ca2e9 100644
--- a/libstdc++-v3/include/bits/atomic_wait.h
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -100,7 +100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),
 				  static_cast<int>(__futex_wait_flags::__wait_private),
 				    __val, nullptr);
-	    if (!__e || EAGAIN)
+	    if (!__e || errno == EAGAIN)
 	      break;
 	    else if (errno != EINTR)
 	      __throw_system_error(__e);
@@ -133,7 +133,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       mutable __gthread_cond_t _M_cv;
       __waiters() noexcept
       {
-	__GTHREAD_COND_INIT_FUNCTION(&_M_cond);
+	__GTHREAD_COND_INIT_FUNCTION(&_M_cv);
       }
 #  endif
 #endif
Jeff Law via Gcc-patches Nov. 25, 2020, 6:39 p.m. | #17
On 25/11/20 10:35 +0000, Jonathan Wakely wrote:
>I've pushed that as ad9cbcee543ecccd79fa49dafcd925532d2ce210 but there

>are still other FAILs to be fixed.


I think the other FAILs are due to a race condition in the tests,
fixed by this patch. Tested x86_64-linux, powerpc64le-linux,
sparc-solaris2.11 and powerpc-aix. Committed to trunk.

I'll keep an eye on the testresults to see if this really fixes it or
not.
commit f76cad692a62d44ed32d010200bad74f36c73092
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Nov 25 14:39:54 2020

    libstdc++: Fix testsuite helper functions [PR 97936]
    
    This fixes a race condition in the util/atomic/wait_notify_util.h header
    used by several tests, which should make the tests work properly.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/97936
            * testsuite/29_atomics/atomic/wait_notify/bool.cc: Re-eneable
            test.
            * testsuite/29_atomics/atomic/wait_notify/generic.cc: Likewise.
            * testsuite/29_atomics/atomic/wait_notify/pointers.cc: Likewise.
            * testsuite/29_atomics/atomic_flag/wait_notify/1.cc: Likewise.
            * testsuite/29_atomics/atomic_float/wait_notify.cc: Likewise.
            * testsuite/29_atomics/atomic_integral/wait_notify.cc: Likewise.
            * testsuite/util/atomic/wait_notify_util.h: Fix missed
            notifications by making the new thread wait until the parent
            thread is waiting on the condition variable.

diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
index 29781c6e1357..c14a2391d68b 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
@@ -2,7 +2,6 @@
 // { dg-do run { target c++2a } }
 // { dg-require-gthreads "" }
 // { dg-additional-options "-pthread" { target pthread } }
-// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
index 629556a9d2d0..988fe7b334f3 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
@@ -2,7 +2,6 @@
 // { dg-do run { target c++2a } }
 // { dg-require-gthreads "" }
 // { dg-additional-options "-pthread" { target pthread } }
-// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
index f54961f893d4..87830236e0ee 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
@@ -2,7 +2,6 @@
 // { dg-do run { target c++2a } }
 // { dg-additional-options "-pthread" { target pthread } }
 // { dg-require-gthreads "" }
-// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
index 763d3e77159c..991713fbcdee 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
@@ -2,7 +2,6 @@
 // { dg-do run { target c++2a } }
 // { dg-require-gthreads "" }
 // { dg-additional-options "-pthread" { target pthread } }
-// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
index 8f9e4a39a21f..134eff39e1b1 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
@@ -3,7 +3,6 @@
 // { dg-require-gthreads "" }
 // { dg-additional-options "-pthread" { target pthread } }
 // { dg-add-options libatomic }
-// { dg-skip-if "broken" { ! *-*-*linux } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
index 762583cf8c76..c65379cba619 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
@@ -3,7 +3,6 @@
 // { dg-require-gthreads "" }
 // { dg-add-options libatomic }
 // { dg-additional-options "-pthread" { target pthread } }
-// { dg-skip-if "broken" { *-*-* } }
 
 // Copyright (C) 2020 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h b/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h
index a319e8b60a69..f5fff4af4e49 100644
--- a/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h
+++ b/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h
@@ -34,16 +34,20 @@ Tp check_wait_notify(Tp val1, Tp val2)
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic<Tp> a(val1);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(val1);
 		  if (a.load() != val2)
 		    a = val1;
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(val2);
@@ -59,10 +63,15 @@ Tp check_wait_notify(Tp val1, Tp val2)
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic<Tp> a(val1);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(val1);
 		  auto v = a.load();
@@ -70,7 +79,6 @@ Tp check_wait_notify(Tp val1, Tp val2)
 		  if (__builtin_memcmp(&v, &val2, sizeof(Tp)) != 0)
 		    a = val1;
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(val2);
@@ -87,16 +95,20 @@ Tp check_atomic_wait_notify(Tp val1, Tp val2)
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic<Tp> a(val1);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  std::atomic_wait(&a, val1);
 		  if (a.load() != val2)
 		    a = val1;
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(val2);
@@ -112,10 +124,15 @@ Tp check_atomic_wait_notify(Tp val1, Tp val2)
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic<Tp> a(val1);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  std::atomic_wait(&a, val1);
 		  auto v = a.load();
@@ -123,7 +140,6 @@ Tp check_atomic_wait_notify(Tp val1, Tp val2)
 		  if (__builtin_memcmp(&v, &val2, sizeof(Tp)) != 0)
 		    a = val1;
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(val2);
Jeff Law via Gcc-patches Nov. 26, 2020, 4:26 p.m. | #18
On 25/11/20 18:39 +0000, Jonathan Wakely wrote:
>On 25/11/20 10:35 +0000, Jonathan Wakely wrote:

>>I've pushed that as ad9cbcee543ecccd79fa49dafcd925532d2ce210 but there

>>are still other FAILs to be fixed.

>

>I think the other FAILs are due to a race condition in the tests,

>fixed by this patch. Tested x86_64-linux, powerpc64le-linux,

>sparc-solaris2.11 and powerpc-aix. Committed to trunk.

>

>I'll keep an eye on the testresults to see if this really fixes it or

>not.


This fixes some more races of the same kind, in different tiles.

Tested as above. Committed to trunk.
commit 10522ed1089277e2aa6cd708205aa5c730179cf0
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 26 12:55:47 2020

    libstdc++: Fix some more deadlocks in tests [PR 97936]
    
    The missed notifications fixed in r11-5383 also happen in some other
    tests which have similar code.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/97936
            * testsuite/29_atomics/atomic/wait_notify/bool.cc: Fix missed
            notifications by making the new thread wait until the parent
            thread is waiting on the condition variable.
            * testsuite/29_atomics/atomic/wait_notify/pointers.cc: Likewise.
            * testsuite/29_atomics/atomic_flag/wait_notify/1.cc: Likewise.
            * testsuite/29_atomics/atomic_ref/wait_notify.cc: Likewise.

diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
index c14a2391d68b..1fc014911737 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
@@ -36,11 +36,16 @@ main ()
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic<bool> a(false);
   std::atomic<bool> b(false);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(false);
 		  if (a.load())
@@ -48,7 +53,6 @@ main ()
 		      b.store(true);
 		    }
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(true);
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
index 87830236e0ee..3b699e9133b2 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
@@ -36,6 +36,7 @@ main ()
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   long aa;
   long bb;
@@ -43,12 +44,15 @@ main ()
   std::atomic<long*> a(nullptr);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(nullptr);
 		  if (a.load() == &aa)
 		    a.store(&bb);
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(&aa);
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
index 991713fbcdee..5d5e06dde31c 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
@@ -36,18 +36,22 @@ main()
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   std::atomic_flag a;
   std::atomic_flag b;
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(false);
 		  b.test_and_set();
 		  b.notify_one();
 		});
 
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.test_and_set();
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
index b38fc206d468..bc5a7d0d8bf9 100644
--- a/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
@@ -37,17 +37,21 @@ Tp check_wait_notify(Tp val1, Tp val2)
 
   std::mutex m;
   std::condition_variable cv;
+  std::unique_lock<std::mutex> l(m);
 
   Tp aa = val1;
   std::atomic_ref<Tp> a(aa);
   std::thread t([&]
 		{
+		  {
+		    // This ensures we block until cv.wait(l) starts.
+		    std::lock_guard<std::mutex> ll(m);
+		  }
 		  cv.notify_one();
 		  a.wait(val1);
 		  if (a.load() != val2)
 		    a = val1;
 		});
-  std::unique_lock<std::mutex> l(m);
   cv.wait(l);
   std::this_thread::sleep_for(100ms);
   a.store(val2);

Patch

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index c90ac555e15..382e94322c1 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -52,6 +52,7 @@  std_headers = \
 	${std_srcdir}/iostream \
 	${std_srcdir}/istream \
 	${std_srcdir}/iterator \
+	${std_srcdir}/latch \
 	${std_srcdir}/limits \
 	${std_srcdir}/list \
 	${std_srcdir}/locale \
@@ -69,6 +70,7 @@  std_headers = \
 	${std_srcdir}/ratio \
 	${std_srcdir}/regex \
 	${std_srcdir}/scoped_allocator \
+	${std_srcdir}/semaphore \
 	${std_srcdir}/set \
 	${std_srcdir}/shared_mutex \
 	${std_srcdir}/span \
@@ -102,6 +104,8 @@  bits_headers = \
 	${bits_srcdir}/allocator.h \
 	${bits_srcdir}/atomic_base.h \
 	${bits_srcdir}/atomic_futex.h \
+	${bits_srcdir}/atomic_timed_wait.h \
+	${bits_srcdir}/atomic_wait.h \
 	${bits_srcdir}/basic_ios.h \
 	${bits_srcdir}/basic_ios.tcc \
 	${bits_srcdir}/basic_string.h \
@@ -177,6 +181,7 @@  bits_headers = \
 	${bits_srcdir}/regex_compiler.tcc \
 	${bits_srcdir}/regex_executor.h \
 	${bits_srcdir}/regex_executor.tcc \
+	${bits_srcdir}/semaphore_base.h \
 	${bits_srcdir}/shared_ptr.h \
 	${bits_srcdir}/shared_ptr_atomic.h \
 	${bits_srcdir}/shared_ptr_base.h \
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index 2cdd2bd6cae..dd4db926592 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -37,6 +37,10 @@ 
 #include <bits/atomic_lockfree_defines.h>
 #include <bits/move.h>
 
+#if __cplusplus > 201703L
+#include <bits/atomic_wait.h>
+#endif
+
 #ifndef _GLIBCXX_ALWAYS_INLINE
 #define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
 #endif
@@ -134,7 +138,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __ret;
     }
 
-
   // Base types for atomics.
   template<typename _IntTp>
     struct __atomic_base;
@@ -226,6 +229,29 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __atomic_load(&_M_i, &__v, int(__m));
       return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
     }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    wait(bool __old,
+	memory_order __m = memory_order_seq_cst) const noexcept
+    {
+      std::__atomic_wait(&_M_i, __old,
+			 [__m, this, __old]()
+			 { return this->test(__m) != __old; });
+    }
+
+    // TODO add const volatile overload
+
+    _GLIBCXX_ALWAYS_INLINE void
+    notify_one() const noexcept
+    { std::__atomic_notify(&_M_i, false); }
+
+    // TODO add const volatile overload
+
+    _GLIBCXX_ALWAYS_INLINE void
+    notify_all() const noexcept
+    { std::__atomic_notify(&_M_i, true); }
+
+    // TODO add const volatile overload
 #endif // C++20
 
     _GLIBCXX_ALWAYS_INLINE void
@@ -576,6 +602,31 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__m));
       }
 
+#if __cplusplus > 201703L
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(__int_type __old,
+	  memory_order __m = memory_order_seq_cst) const noexcept
+      {
+	std::__atomic_wait(&_M_i, __old,
+			   [__m, this, __old]
+			   { return this->load(__m) != __old; });
+      }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { std::__atomic_notify(&_M_i, false); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { std::__atomic_notify(&_M_i, true); }
+
+      // TODO add const volatile overload
+#endif // C++2a
+
       _GLIBCXX_ALWAYS_INLINE __int_type
       fetch_add(__int_type __i,
 		memory_order __m = memory_order_seq_cst) noexcept
@@ -845,6 +896,31 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 					   int(__m1), int(__m2));
       }
 
+#if __cplusplus > 201703L
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(__pointer_type __old,
+	   memory_order __m = memory_order_seq_cst) noexcept
+      {
+	std::__atomic_wait(&_M_p, __old,
+		      [__m, this, __old]()
+		      { return this->load(__m) != __old; });
+      }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { std::__atomic_notify(&_M_p, false); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { std::__atomic_notify(&_M_p, true); }
+
+      // TODO add const volatile overload
+#endif // C++2a
+
       _GLIBCXX_ALWAYS_INLINE __pointer_type
       fetch_add(ptrdiff_t __d,
 		memory_order __m = memory_order_seq_cst) noexcept
@@ -933,6 +1009,33 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 					 int(__success), int(__failure));
       }
 
+#if __cplusplus > 201703L
+    template<typename _Tp>
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(const _Tp* __ptr, _Val<_Tp> __old,
+	   memory_order __m = memory_order_seq_cst) noexcept
+      {
+	std::__atomic_wait(__ptr, __old,
+	    [=]() { return load(__ptr, __m) == __old; });
+      }
+
+      // TODO add const volatile overload
+
+    template<typename _Tp>
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one(const _Tp* __ptr) noexcept
+      { std::__atomic_notify(__ptr, false); }
+
+      // TODO add const volatile overload
+
+    template<typename _Tp>
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all(const _Tp* __ptr) noexcept
+      { std::__atomic_notify(__ptr, true); }
+
+      // TODO add const volatile overload
+#endif // C++2a
+
     template<typename _Tp>
       _GLIBCXX_ALWAYS_INLINE _Tp
       fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept
@@ -1186,6 +1289,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__order));
       }
 
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
+      { __atomic_impl::wait(&_M_fp, __old, __m); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { __atomic_impl::notify_one(&_M_fp); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { __atomic_impl::notify_all(&_M_fp); }
+
+      // TODO add const volatile overload
+
       value_type
       fetch_add(value_type __i,
 		memory_order __m = memory_order_seq_cst) noexcept
@@ -1323,6 +1444,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__order));
       }
 
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
+      { __atomic_impl::wait(_M_ptr, __old, __m); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { __atomic_impl::notify_one(_M_ptr); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { __atomic_impl::notify_all(_M_ptr); }
+
+      // TODO add const volatile overload
+
     private:
       _Tp* _M_ptr;
     };
@@ -1418,6 +1557,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__order));
       }
 
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
+      { __atomic_impl::wait(_M_ptr, __old, __m); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { __atomic_impl::notify_one(_M_ptr); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { __atomic_impl::notify_all(_M_ptr); }
+
+      // TODO add const volatile overload
+
       value_type
       fetch_add(value_type __i,
 		memory_order __m = memory_order_seq_cst) const noexcept
@@ -1573,6 +1730,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__order));
       }
 
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept
+      { __atomic_impl::wait(_M_ptr, __old, __m); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { __atomic_impl::notify_one(_M_ptr); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { __atomic_impl::notify_all(_M_ptr); }
+
+      // TODO add const volatile overload
+
       value_type
       fetch_add(value_type __i,
 		memory_order __m = memory_order_seq_cst) const noexcept
@@ -1682,6 +1857,24 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				       __cmpexch_failure_order(__order));
       }
 
+      _GLIBCXX_ALWAYS_INLINE void
+      wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
+      { __atomic_impl::wait(_M_ptr, __old, __m); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_one() const noexcept
+      { __atomic_impl::notify_one(_M_ptr); }
+
+      // TODO add const volatile overload
+
+      _GLIBCXX_ALWAYS_INLINE void
+      notify_all() const noexcept
+      { __atomic_impl::notify_all(_M_ptr); }
+
+      // TODO add const volatile overload
+
       _GLIBCXX_ALWAYS_INLINE value_type
       fetch_add(difference_type __d,
 		memory_order __m = memory_order_seq_cst) const noexcept
diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h
new file mode 100644
index 00000000000..7712a6c591d
--- /dev/null
+++ b/libstdc++-v3/include/bits/atomic_timed_wait.h
@@ -0,0 +1,287 @@ 
+// -*- C++ -*- header.
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/atomic_timed_wait.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{atomic}
+ */
+
+#ifndef _GLIBCXX_ATOMIC_TIMED_WAIT_H
+#define _GLIBCXX_ATOMIC_TIMED_WAIT_H 1
+
+#pragma GCC system_header
+
+#include <bits/c++config.h>
+#include <bits/functional_hash.h>
+#include <bits/atomic_wait.h>
+
+#include <chrono>
+
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+#include <sys/time.h>
+#endif
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  enum class __atomic_wait_status { no_timeout, timeout };
+
+  namespace __detail
+  {
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+    using __platform_wait_clock_t = chrono::steady_clock;
+
+    template<typename _Duration>
+      __atomic_wait_status
+      __platform_wait_until_impl(__platform_wait_t* __addr,
+				 __platform_wait_t __val,
+				 const chrono::time_point<
+					  __platform_wait_clock_t, _Duration>&
+				      __atime) noexcept
+      {
+	auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
+	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+
+	struct timespec __rt =
+	{
+	  static_cast<std::time_t>(__s.time_since_epoch().count()),
+	  static_cast<long>(__ns.count())
+	};
+
+	auto __e = syscall (SYS_futex, __addr,
+			    static_cast<int>(__futex_wait_flags::
+						__wait_bitset_private),
+			    __val, &__rt, nullptr,
+			    static_cast<int>(__futex_wait_flags::
+						__bitset_match_any));
+	if (__e && !(errno == EINTR || errno == EAGAIN || errno == ETIMEDOUT))
+	    std::terminate();
+	return (__platform_wait_clock_t::now() < __atime)
+	       ? __atomic_wait_status::no_timeout
+	       : __atomic_wait_status::timeout;
+      }
+
+    template<typename _Clock, typename _Duration>
+      __atomic_wait_status
+      __platform_wait_until(__platform_wait_t* __addr, __platform_wait_t __val,
+			    const chrono::time_point<_Clock, _Duration>&
+				__atime)
+      {
+	if constexpr (is_same_v<__platform_wait_clock_t, _Clock>)
+	  {
+	    return __detail::__platform_wait_until_impl(__addr, __val, __atime);
+	  }
+	else
+	  {
+	    const typename _Clock::time_point __c_entry = _Clock::now();
+	    const __platform_wait_clock_t::time_point __s_entry =
+		    __platform_wait_clock_t::now();
+	    const auto __delta = __atime - __c_entry;
+	    const auto __s_atime = __s_entry + __delta;
+	    if (__detail::__platform_wait_until_impl(__addr, __val, __s_atime)
+		  == __atomic_wait_status::no_timeout)
+	      return __atomic_wait_status::no_timeout;
+
+	    // We got a timeout when measured against __clock_t but
+	    // we need to check against the caller-supplied clock
+	    // to tell whether we should return a timeout.
+	    if (_Clock::now() < __atime)
+	      return __atomic_wait_status::no_timeout;
+	    return __atomic_wait_status::timeout;
+	  }
+      }
+#endif
+
+#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
+    template<typename _Duration>
+      __atomic_wait_status
+      __cond_wait_until_impl(__gthread_cond_t* __cv,
+	  unique_lock<mutex>& __lock,
+	  const chrono::time_point<chrono::steady_clock, _Duration>& __atime)
+      {
+	auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
+	auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+
+	__gthread_time_t __ts =
+	  {
+	    static_cast<std::time_t>(__s.time_since_epoch().count()),
+	    static_cast<long>(__ns.count())
+	  };
+
+	pthread_cond_clockwait(__cv, __lock.mutex()->native_handle(),
+			       CLOCK_MONOTONIC,
+			       &__ts);
+	return (chrono::steady_clock::now() < __atime)
+	       ? __atomic_wait_status::no_timeout
+	       : __atomic_wait_status::timeout;
+      }
+#endif
+
+      template<typename _Duration>
+	__atomic_wait_status
+	__cond_wait_until_impl(__gthread_cond_t* __cv,
+	    unique_lock<std::mutex>& __lock,
+	    const chrono::time_point<chrono::system_clock, _Duration>& __atime)
+	{
+	  auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
+	  auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+
+	  __gthread_time_t __ts =
+	  {
+	    static_cast<std::time_t>(__s.time_since_epoch().count()),
+	    static_cast<long>(__ns.count())
+	  };
+
+	  __gthread_cond_timedwait(__cv, __lock.mutex()->native_handle(),
+				   &__ts);
+	  return (chrono::system_clock::now() < __atime)
+		 ? __atomic_wait_status::no_timeout
+		 : __atomic_wait_status::timeout;
+	}
+
+      // return true if timeout
+      template<typename _Clock, typename _Duration>
+	__atomic_wait_status
+	__cond_wait_until(__gthread_cond_t* __cv,
+	    unique_lock<std::mutex>& __lock,
+	    const chrono::time_point<_Clock, _Duration>& __atime)
+	{
+#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT
+	  using __clock_t = chrono::steady_clock;
+#else
+	  using __clock_t = chrono::system_clock;
+#endif
+	  const typename _Clock::time_point __c_entry = _Clock::now();
+	  const __clock_t::time_point __s_entry = __clock_t::now();
+	  const auto __delta = __atime - __c_entry;
+	  const auto __s_atime = __s_entry + __delta;
+	  if (std::__detail::__cond_wait_until_impl(__cv, __lock, __s_atime))
+	    return __atomic_wait_status::no_timeout;
+	  // We got a timeout when measured against __clock_t but
+	  // we need to check against the caller-supplied clock
+	  // to tell whether we should return a timeout.
+	  if (_Clock::now() < __atime)
+	    return __atomic_wait_status::no_timeout;
+	  return __atomic_wait_status::timeout;
+	}
+
+    struct __timed_waiters : __waiters
+    {
+      template<typename _Clock, typename _Duration>
+	__atomic_wait_status
+	_M_do_wait_until(__platform_wait_t __version,
+			 const chrono::time_point<_Clock, _Duration>& __atime)
+	{
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+	  return __detail::__platform_wait_until(&_M_ver, __version, __atime);
+#else
+	  __platform_wait_t __cur = 0;
+	  __waiters::__lock_t __l(_M_mtx);
+	  while (__cur <= __version)
+	    {
+	      if (__detail::__cond_wait_until(&_M_cv, __l, __atime)
+		    == __atomic_wait_status::timeout)
+		return __atomic_wait_status::timeout;
+
+	      __platform_wait_t __last = __cur;
+	      __atomic_load(&_M_ver, &__cur, __ATOMIC_ACQUIRE);
+	      if (__cur < __last)
+		break; // break the loop if version overflows
+	    }
+	  return __atomic_wait_status::no_timeout;
+#endif
+	}
+
+      static __timed_waiters&
+      _S_timed_for(void* __t)
+      {
+	static_assert(sizeof(__timed_waiters) == sizeof(__waiters));
+	return static_cast<__timed_waiters&>(__waiters::_S_for(__t));
+      }
+    };
+  } // namespace __detail
+
+  template<typename _Tp, typename _Pred,
+	   typename _Clock, typename _Duration>
+    bool
+    __atomic_wait_until(const _Tp* __addr, _Tp __old, _Pred __pred,
+			const chrono::time_point<_Clock, _Duration>&
+			    __atime) noexcept
+    {
+      using namespace __detail;
+
+      if (std::__atomic_spin(__pred))
+	return true;
+
+      auto& __w = __timed_waiters::_S_timed_for((void*)__addr);
+      auto __version = __w._M_enter_wait();
+      do
+	{
+	  __atomic_wait_status __res;
+	  if constexpr (__platform_wait_uses_type<_Tp>)
+	    {
+	      __res = __detail::__platform_wait_until((__platform_wait_t*)(void*) __addr,
+						      __old, __atime);
+	    }
+	  else
+	    {
+	      __res = __w._M_do_wait_until(__version, __atime);
+	    }
+	  if (__res == __atomic_wait_status::timeout)
+	    return false;
+	}
+      while (!__pred() && __atime < _Clock::now());
+      __w._M_leave_wait();
+
+      // if timed out, return false
+      return (_Clock::now() < __atime);
+    }
+
+  template<typename _Tp, typename _Pred,
+	   typename _Rep, typename _Period>
+    bool
+    __atomic_wait_for(const _Tp* __addr, _Tp __old, _Pred __pred,
+		      const chrono::duration<_Rep, _Period>& __rtime) noexcept
+    {
+      using namespace __detail;
+
+      if (std::__atomic_spin(__pred))
+	return true;
+
+      if (!__rtime.count())
+	return false; // no rtime supplied, and spin did not acquire
+
+      using __dur = chrono::steady_clock::duration;
+      auto __reltime = chrono::duration_cast<__dur>(__rtime);
+      if (__reltime < __rtime)
+	++__reltime;
+
+
+      return __atomic_wait_until(__addr, __old, std::move(__pred),
+				 chrono::steady_clock::now() + __reltime);
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif
diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h
new file mode 100644
index 00000000000..2d08e5325fb
--- /dev/null
+++ b/libstdc++-v3/include/bits/atomic_wait.h
@@ -0,0 +1,306 @@ 
+// -*- C++ -*- header.
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/atomic_wait.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{atomic}
+ */
+
+#ifndef _GLIBCXX_ATOMIC_WAIT_H
+#define _GLIBCXX_ATOMIC_WAIT_H 1
+
+#pragma GCC system_header
+
+#include <bits/c++config.h>
+#include <bits/functional_hash.h>
+#include <bits/gthr.h>
+#include <bits/std_mutex.h>
+#include <bits/unique_lock.h>
+#include <ext/numeric_traits.h>
+
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+#include <climits>
+#include <unistd.h>
+#include <syscall.h>
+#endif
+
+
+// TODO get this from Autoconf
+#define _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE 1
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+  namespace __detail
+  {
+    using __platform_wait_t = int;
+
+    constexpr auto __atomic_spin_count_1 = 16;
+    constexpr auto __atomic_spin_count_2 = 12;
+
+    inline constexpr
+    auto __platform_wait_max_value =
+		__gnu_cxx::__int_traits<__platform_wait_t>::__max;
+
+    template<typename _Tp>
+      inline constexpr bool __platform_wait_uses_type
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+	= is_same_v<remove_cv_t<_Tp>, __platform_wait_t>;
+#else
+	= false;
+#endif
+
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+    enum class __futex_wait_flags : int
+    {
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE
+      __private_flag = 128,
+#else
+      __private_flag = 0,
+#endif
+      __wait = 0,
+      __wake = 1,
+      __wait_bitset = 9,
+      __wake_bitset = 10,
+      __wait_private = __wait | __private_flag,
+      __wake_private = __wake | __private_flag,
+      __wait_bitset_private = __wait_bitset | __private_flag,
+      __wake_bitset_private = __wake_bitset | __private_flag,
+      __bitset_match_any = -1
+    };
+
+    template<typename _Tp>
+      void
+      __platform_wait(const _Tp* __addr, __platform_wait_t __val) noexcept
+      {
+	for(;;)
+	  {
+	    auto __e = syscall (SYS_futex, static_cast<const void*>(__addr),
+				  static_cast<int>(__futex_wait_flags::__wait_private),
+				    __val, nullptr);
+	    if (!__e)
+	      break;
+	    else if (!(errno == EINTR || errno == EAGAIN))
+	      __throw_system_error(__e);
+	  }
+      }
+
+      template<typename _Tp>
+      void
+      __platform_notify(const _Tp* __addr, bool __all) noexcept
+      {
+	syscall (SYS_futex, static_cast<const void*>(__addr),
+		  static_cast<int>(__futex_wait_flags::__wake_private),
+		    __all ? INT_MAX : 1);
+      }
+#endif
+
+    struct __waiters
+    {
+       alignas(64) __platform_wait_t _M_ver = 0;
+       alignas(64) __platform_wait_t _M_wait = 0;
+
+#ifndef _GLIBCXX_HAVE_LINUX_FUTEX
+      using __lock_t = std::unique_lock<std::mutex>;
+      mutable __lock_t::mutex_type _M_mtx;
+
+#  ifdef __GTHREAD_COND_INIT
+      mutable __gthread_cond_t _M_cv = __GTHREAD_COND_INIT;
+      __waiters() noexcept = default;
+#  else
+      mutable __gthread_cond_t _M_cv;
+      __waiters() noexcept
+      {
+	__GTHREAD_COND_INIT_FUNCTION(&_M_cond);
+      }
+#  endif
+#endif
+
+      __platform_wait_t
+      _M_enter_wait() noexcept
+      {
+	__platform_wait_t __res;
+	__atomic_load(&_M_ver, &__res, __ATOMIC_ACQUIRE);
+	__atomic_fetch_add(&_M_wait, 1, __ATOMIC_ACQ_REL);
+	return __res;
+      }
+
+      void
+      _M_leave_wait() noexcept
+      {
+	__atomic_fetch_sub(&_M_wait, 1, __ATOMIC_ACQ_REL);
+      }
+
+      void
+      _M_do_wait(__platform_wait_t __version) noexcept
+      {
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+	__platform_wait(&_M_ver, __version);
+#else
+	__platform_wait_t __cur = 0;
+	while (__cur <= __version)
+	  {
+	    __waiters::__lock_t __l(_M_mtx);
+	    auto __e = __gthread_cond_wait(&_M_cv, __l.mutex()->native_handle());
+	    if (__e)
+	      __throw_system_error(__e);
+	    __platform_wait_t __last = __cur;
+	    __atomic_load(&_M_ver, &__cur, __ATOMIC_ACQUIRE);
+	    if (__cur < __last)
+	      break; // break the loop if version overflows
+	  }
+#endif
+      }
+
+      bool
+      _M_waiting() const noexcept
+	{
+	  __platform_wait_t __res;
+	  __atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE);
+	  return __res;
+	}
+
+      void
+      _M_notify(bool __all) noexcept
+      {
+	__atomic_fetch_add(&_M_ver, 1, __ATOMIC_ACQ_REL);
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+	__platform_notify(&_M_ver, __all);
+#else
+	auto __e = __gthread_cond_broadcast(&_M_cv);
+	if (__e)
+	  __throw_system_error(__e);
+#endif
+      }
+
+      static __waiters&
+      _S_for(const void* __t)
+      {
+	const unsigned char __mask = 0xf;
+	static __waiters __w[__mask + 1];
+
+	auto __key = _Hash_impl::hash(__t) & __mask;
+	return __w[__key];
+      }
+    };
+
+    struct __waiter
+    {
+      __waiters& _M_w;
+      __platform_wait_t _M_version;
+
+      template<typename _Tp>
+	__waiter(const _Tp* __addr) noexcept
+	  : _M_w(__waiters::_S_for(static_cast<const void*>(__addr)))
+	  , _M_version(_M_w._M_enter_wait())
+	{ }
+
+      ~__waiter()
+      { _M_w._M_leave_wait(); }
+
+      void _M_do_wait() noexcept
+      { _M_w._M_do_wait(_M_version); }
+    };
+
+    void
+    __thread_relax() noexcept
+    {
+#if defined __i386__ || defined __x86_64__
+      __builtin_ia32_pause();
+#elif defined _GLIBCXX_USE_SCHED_YIELD
+      __gthread_yield();
+#endif
+    }
+
+    void
+    __thread_yield() noexcept
+   {
+#if defined _GLIBCXX_USE_SCHED_YIELD
+     __gthread_yield();
+#endif
+    }
+
+  } // namespace __detail
+
+  template<typename _Pred>
+    bool
+    __atomic_spin(_Pred& __pred) noexcept
+    {
+      for (auto __i = 0; __i < __detail::__atomic_spin_count_1; ++__i)
+	{
+	  if (__pred())
+	    return true;
+
+	  if (__i < __detail::__atomic_spin_count_2)
+	    __detail::__thread_relax();
+	  else
+	    __detail::__thread_yield();
+	}
+      return false;
+    }
+
+  template<typename _Tp, typename _Pred>
+    void
+    __atomic_wait(const _Tp* __addr, _Tp __old, _Pred __pred) noexcept
+    {
+      using namespace __detail;
+      if (std::__atomic_spin(__pred))
+	return;
+
+      __waiter __w(__addr);
+      while (!__pred())
+	{
+	  if constexpr (__platform_wait_uses_type<_Tp>)
+	    {
+	      __platform_wait(__addr, __old);
+	    }
+	  else
+	    {
+	      // TODO support timed backoff when this can be moved into the lib
+	      __w._M_do_wait();
+	    }
+	}
+    }
+
+  template<typename _Tp>
+    void
+    __atomic_notify(const _Tp* __addr, bool __all) noexcept
+    {
+      using namespace __detail;
+      auto& __w = __waiters::_S_for((void*)__addr);
+      if (!__w._M_waiting())
+	return;
+
+      if constexpr (__platform_wait_uses_type<_Tp>)
+	{
+	  __platform_notify((__platform_wait_t*)(void*) __addr, __all);
+	}
+      else
+	{
+	  __w._M_notify(__all);
+	}
+    }
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif
diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h
new file mode 100644
index 00000000000..da6dc4b9185
--- /dev/null
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -0,0 +1,296 @@ 
+// -*- C++ -*- header.
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/semaphore_base.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{semaphore}
+ */
+
+#ifndef _GLIBCXX_SEMAPHORE_BASE_H
+#define _GLIBCXX_SEMAPHORE_BASE_H 1
+
+#pragma GCC system_header
+
+#include <bits/c++config.h>
+#include <bits/atomic_base.h>
+#include <bits/atomic_timed_wait.h>
+
+#include <ext/numeric_traits.h>
+
+#if __has_include(<semaphore.h>)
+#define _GLIBCXX_HAVE_POSIX_SEMAPHORE 1
+#include <semaphore.h>
+#endif
+
+#include <chrono>
+#include <type_traits>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  struct __platform_semaphore
+  {
+    using __clock_t = chrono::system_clock;
+    static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX;
+
+    explicit __platform_semaphore(ptrdiff_t __count) noexcept
+    {
+      sem_init(&_M_semaphore, 0, __count);
+    }
+
+    __platform_semaphore(const __platform_semaphore&) = delete;
+    __platform_semaphore& operator=(const __platform_semaphore&) = delete;
+
+    ~__platform_semaphore()
+    { sem_destroy(&_M_semaphore); }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    _M_acquire() noexcept
+    {
+      for (;;)
+	{
+	  auto __err = sem_wait(&_M_semaphore);
+	  if (__err && (errno == EINTR))
+	    continue;
+	  else if (__err)
+	    std::terminate();
+	  else
+	    break;
+	}
+    }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    _M_release(std::ptrdiff_t __update) noexcept
+    {
+      for(; __update != 0; --__update)
+	{
+	   auto __err = sem_post(&_M_semaphore);
+	   if (__err)
+	     std::terminate();
+	}
+    }
+
+    bool
+    _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime)
+      noexcept
+    {
+
+      auto __s = chrono::time_point_cast<chrono::seconds>(__atime);
+      auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s);
+
+      struct timespec __ts =
+      {
+	static_cast<std::time_t>(__s.time_since_epoch().count()),
+	static_cast<long>(__ns.count())
+      };
+
+      for (;;)
+	{
+	  if (auto __err = sem_timedwait(&_M_semaphore, &__ts))
+	    {
+	      if (errno == EINTR)
+		continue;
+	      else if (errno == ETIMEDOUT || errno == EINVAL)
+		return false;
+	      else
+		std::terminate();
+	    }
+	  else
+	    break;
+	}
+      return true;
+    }
+
+    template<typename _Clock, typename _Duration>
+      bool
+      _M_try_acquire_until(const chrono::time_point<_Clock,
+			   _Duration>& __atime) noexcept
+      {
+	if constexpr (std::is_same_v<__clock_t, _Clock>)
+	  {
+	    return _M_try_acquire_until_impl(__atime);
+	  }
+	else
+	  {
+	    const typename _Clock::time_point __c_entry = _Clock::now();
+	    const __clock_t __s_entry = __clock_t::now();
+	    const auto __delta = __atime - __c_entry;
+	    const auto __s_atime = __s_entry + __delta;
+	    if (_M_try_acquire_until_impl(__s_atime))
+	      return true;
+
+	    // We got a timeout when measured against __clock_t but
+	    // we need to check against the caller-supplied clock
+	    // to tell whether we should return a timeout.
+	    return (_Clock::now() < __atime);
+	  }
+      }
+
+    template<typename _Rep, typename _Period>
+      _GLIBCXX_ALWAYS_INLINE bool
+      _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
+	noexcept
+      { return _M_try_acquire_until(__clock_t::now() + __rtime); }
+
+    private:
+      sem_t _M_semaphore;
+    };
+#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE
+
+    template<typename _Tp>
+      struct __atomic_semaphore
+      {
+	static_assert(std::is_integral_v<_Tp>);
+	static_assert(__gnu_cxx::__int_traits<_Tp>::__max
+			<= __gnu_cxx::__int_traits<ptrdiff_t>::__max);
+	static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<_Tp>::__max;
+
+	explicit __atomic_semaphore(_Tp __count) noexcept
+	  : _M_counter(__count)
+	{
+	  __glibcxx_assert(__count >= 0 && __count <= _S_max);
+	}
+
+	__atomic_semaphore(const __atomic_semaphore&) = delete;
+	__atomic_semaphore& operator=(const __atomic_semaphore&) = delete;
+
+	_GLIBCXX_ALWAYS_INLINE void
+	_M_acquire() noexcept
+	{
+	  auto const __pred = [this]
+	    {
+	      auto __old = __atomic_impl::load(&this->_M_counter,
+			      memory_order::acquire);
+	      if (__old == 0)
+		return false;
+	      return __atomic_impl::compare_exchange_strong(&this->_M_counter,
+			__old, __old - 1,
+			memory_order::acquire,
+			memory_order::release);
+	    };
+	  auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
+	  std::__atomic_wait(&_M_counter, __old, __pred);
+	}
+
+	bool
+	_M_try_acquire() noexcept
+	{
+	  auto __old = __atomic_impl::load(&_M_counter, memory_order::acquire);
+	  auto const __pred = [this, __old]
+	    {
+	      if (__old == 0)
+		return false;
+
+	      auto __prev = __old;
+	      return __atomic_impl::compare_exchange_weak(&this->_M_counter,
+			__prev, __prev - 1,
+			memory_order::acquire,
+			memory_order::release);
+	    };
+	  return std::__atomic_spin(__pred);
+	}
+
+	template<typename _Clock, typename _Duration>
+	  _GLIBCXX_ALWAYS_INLINE bool
+	  _M_try_acquire_until(const chrono::time_point<_Clock,
+			       _Duration>& __atime) noexcept
+	  {
+	    auto const __pred = [this]
+	      {
+		auto __old = __atomic_impl::load(&this->_M_counter,
+				memory_order::acquire);
+		if (__old == 0)
+		  return false;
+		return __atomic_impl::compare_exchange_strong(&this->_M_counter,
+				__old, __old - 1,
+				memory_order::acquire,
+				memory_order::release);
+	      };
+
+	    auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
+	    return __atomic_wait_until(&_M_counter, __old, __pred, __atime);
+	}
+
+      template<typename _Rep, typename _Period>
+	_GLIBCXX_ALWAYS_INLINE bool
+	_M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime)
+	  noexcept
+	{
+	  auto const __pred = [this]
+	    {
+	      auto __old = __atomic_impl::load(&this->_M_counter,
+			      memory_order::acquire);
+	      if (__old == 0)
+		return false;
+	      return  __atomic_impl::compare_exchange_strong(&this->_M_counter,
+			      __old, __old - 1,
+			      memory_order::acquire,
+			      memory_order::release);
+	    };
+
+	  auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed);
+	  return __atomic_wait_for(&_M_counter, __old, __pred, __rtime);
+	}
+
+      _GLIBCXX_ALWAYS_INLINE void
+      _M_release(ptrdiff_t __update) noexcept
+      {
+	if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release))
+	  return;
+	if (__update > 1)
+	  __atomic_impl::notify_all(&_M_counter);
+	else
+	  __atomic_impl::notify_one(&_M_counter);
+      }
+
+    private:
+      alignas(__alignof__(_Tp)) _Tp _M_counter;
+    };
+
+// Note: the _GLIBCXX_REQUIRE_POSIX_SEMAPHORE macro can be used to force the
+// use of Posix semaphores (sem_t). Doing so however, alters the ABI.
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX && !_GLIBCXX_REQUIRE_POSIX_SEMAPHORE
+  // Use futex if available and didn't force use of POSIX
+  using __fast_semaphore = __atomic_semaphore<__detail::__platform_wait_t>;
+#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  using __fast_semaphore = __platform_semaphore;
+#else
+  using __fast_semaphore = __atomic_semaphore<ptrdiff_t>;
+#endif
+
+template<ptrdiff_t __least_max_value>
+  using __semaphore_impl = conditional_t<
+		(__least_max_value > 1),
+		conditional_t<
+		    (__least_max_value <= __fast_semaphore::_S_max),
+		    __fast_semaphore,
+		    __atomic_semaphore<ptrdiff_t>>,
+		__fast_semaphore>;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index 1a304261fe7..5afe33b41d9 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -163,6 +163,20 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     compare_exchange_strong(bool& __i1, bool __i2,
 		    memory_order __m = memory_order_seq_cst) volatile noexcept
     { return _M_base.compare_exchange_strong(__i1, __i2, __m); }
+
+#if __cplusplus > 201703L
+    void wait(bool __old, memory_order __m = memory_order_seq_cst) const
+      noexcept
+    { _M_base.wait(__old, __m); }
+
+    // TODO add const volatile overload
+
+    void notify_one() const noexcept
+    { _M_base.notify_one(); }
+
+    void notify_all() const noexcept
+    { _M_base.notify_all(); }
+#endif
   };
 
 #if __cplusplus <= 201703L
@@ -363,6 +377,30 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		     memory_order __m = memory_order_seq_cst) volatile noexcept
       { return compare_exchange_strong(__e, __i, __m,
                                        __cmpexch_failure_order(__m)); }
+
+#if __cplusplus > 201703L
+    void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept
+    {
+      std::__atomic_wait(&_M_i, __old,
+			 [__m, this, __old]
+			 {
+			   const auto __v = this->load(__m);
+			   // TODO make this ignore padding bits when we
+			   // can do that
+			   return __builtin_memcmp(&__old, &__v,
+						    sizeof(_Tp)) != 0;
+			 });
+    }
+
+    // TODO add const volatile overload
+
+    void notify_one() const noexcept
+    { std::__atomic_notify(&_M_i, false); }
+
+    void notify_all() const noexcept
+    { std::__atomic_notify(&_M_i, true); }
+#endif
+
     };
 #undef _GLIBCXX20_INIT
 
@@ -601,6 +639,19 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 					    __cmpexch_failure_order(__m));
       }
 
+#if __cplusplus > 201703L
+    void wait(__pointer_type __old,
+	      memory_order __m = memory_order_seq_cst) noexcept
+    { _M_b.wait(__old, __m); }
+
+    // TODO add const volatile overload
+
+    void notify_one() const noexcept
+    { _M_b.notify_one(); }
+
+    void notify_all() const noexcept
+    { _M_b.notify_all(); }
+#endif
       __pointer_type
       fetch_add(ptrdiff_t __d,
 		memory_order __m = memory_order_seq_cst) noexcept
@@ -1353,6 +1404,33 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 						     memory_order_seq_cst);
     }
 
+
+#if __cplusplus > 201703L
+  template<typename _Tp>
+    inline void
+    atomic_wait(const atomic<_Tp>* __a,
+	        typename std::atomic<_Tp>::value_type __old) noexcept
+    { __a->wait(__old); }
+
+  template<typename _Tp>
+    inline void
+    atomic_wait_explicit(const atomic<_Tp>* __a,
+			 typename std::atomic<_Tp>::value_type __old,
+			 std::memory_order __m) noexcept
+    { __a->wait(__old, __m); }
+
+  template<typename _Tp>
+    inline void
+    atomic_notify_one(atomic<_Tp>* __a) noexcept
+    { __a->notify_one(); }
+
+  template<typename _Tp>
+    inline void
+    atomic_notify_all(atomic<_Tp>* __a) noexcept
+    { __a->notify_all(); }
+
+#endif // C++2a
+
   // Function templates for atomic_integral and atomic_pointer operations only.
   // Some operations (and, or, xor) are only available for atomic integrals,
   // which is implemented by taking a parameter of type __atomic_base<_ITp>*.
diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch
new file mode 100644
index 00000000000..9d9c880a88b
--- /dev/null
+++ b/libstdc++-v3/include/std/latch
@@ -0,0 +1,91 @@ 
+// <latch> -*- C++ -*-
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.	This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.	 If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/latch
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_LATCH
+#define _GLIBCXX_LATCH
+
+#pragma GCC system_header
+
+#if __cplusplus > 201703L
+#define __cpp_lib_latch 201907L
+
+#include <bits/atomic_base.h>
+#include <ext/numeric_traits.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  class latch
+  {
+  public:
+    static constexpr ptrdiff_t
+    max() noexcept
+    { return __gnu_cxx::__int_traits<ptrdiff_t>::__max; }
+
+    constexpr explicit latch(ptrdiff_t __expected) noexcept
+      : _M_a(__expected) { }
+
+    ~latch() = default;
+    latch(const latch&) = delete;
+    latch& operator=(const latch&) = delete;
+
+    _GLIBCXX_ALWAYS_INLINE void
+    count_down(ptrdiff_t __update = 1)
+    {
+      auto const __old = __atomic_impl::fetch_sub(&_M_a,
+				    __update, memory_order::release);
+      if (__old == __update)
+	__atomic_impl::notify_all(&_M_a);
+    }
+
+    _GLIBCXX_ALWAYS_INLINE bool
+    try_wait() const noexcept
+    { return __atomic_impl::load(&_M_a, memory_order::acquire) == 0; }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    wait() const noexcept
+    {
+      auto const __old = __atomic_impl::load(&_M_a, memory_order::acquire);
+      std::__atomic_wait(&_M_a, __old, [this] { return this->try_wait(); });
+    }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    arrive_and_wait(ptrdiff_t __update = 1) noexcept
+    {
+      count_down(__update);
+      wait();
+    }
+
+  private:
+    alignas(__alignof__(ptrdiff_t)) ptrdiff_t _M_a;
+  };
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif // __cplusplus > 201703L
+#endif // _GLIBCXX_LATCH
diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore
new file mode 100644
index 00000000000..b4facde4ea1
--- /dev/null
+++ b/libstdc++-v3/include/std/semaphore
@@ -0,0 +1,92 @@ 
+// <semaphore> -*- C++ -*-
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.	This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.	 If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/semaphore
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_SEMAPHORE
+#define _GLIBCXX_SEMAPHORE
+
+#pragma GCC system_header
+
+#if __cplusplus > 201703L
+#define __cpp_lib_semaphore 201907L
+#include <bits/semaphore_base.h>
+#include <ext/numeric_traits.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<ptrdiff_t __least_max_value =
+			__gnu_cxx::__int_traits<ptrdiff_t>::__max>
+    class counting_semaphore
+    {
+      static_assert(__least_max_value >= 0);
+
+      __semaphore_impl<__least_max_value> _M_sem;
+
+    public:
+      explicit counting_semaphore(ptrdiff_t __desired) noexcept
+	: _M_sem(__desired)
+      { }
+
+      ~counting_semaphore() = default;
+
+      counting_semaphore(const counting_semaphore&) = delete;
+      counting_semaphore& operator=(const counting_semaphore&) = delete;
+
+      static constexpr ptrdiff_t
+      max() noexcept
+      { return __least_max_value; }
+
+      void
+      release(ptrdiff_t __update = 1) noexcept(noexcept(_M_sem._M_release(1)))
+      { _M_sem._M_release(__update); }
+
+      void
+      acquire() noexcept(noexcept(_M_sem._M_acquire()))
+      { _M_sem._M_acquire(); }
+
+      bool
+      try_acquire() noexcept(noexcept(_M_sem._M_try_acquire()))
+      { return _M_sem._M_try_acquire(); }
+
+      template<typename _Rep, typename _Period>
+	bool
+	try_acquire_for(const std::chrono::duration<_Rep, _Period>& __rtime)
+	{ return _M_sem._M_try_acquire_for(__rtime); }
+
+      template<typename _Clock, typename _Dur>
+	bool
+	try_acquire_until(const std::chrono::time_point<_Clock, _Dur>& __atime)
+	{ return _M_sem._M_try_acquire_until(__atime); }
+    };
+
+ using binary_semaphore = std::counting_semaphore<1>;
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif // __cplusplus > 201703L
+#endif // _GLIBCXX_SEMAPHORE
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index ebb50a04d24..dcfbbb9ee54 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -216,6 +216,7 @@ 
 #ifdef _GLIBCXX_HAS_GTHREADS
 # define __cpp_lib_jthread 201911L
 #endif
+#define __cpp_lib_latch 201907L
 #define __cpp_lib_list_remove_return_type 201806L
 #if __cpp_lib_concepts
 # define __cpp_lib_make_obj_using_allocator 201811L
@@ -225,6 +226,7 @@ 
 #if __cpp_lib_concepts
 # define __cpp_lib_ranges 201911L
 #endif
+#define __cpp_lib_semaphore 201907L
 #define __cpp_lib_shift 201806L
 #define __cpp_lib_span 202002L
 #define __cpp_lib_ssize 201902L
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
new file mode 100644
index 00000000000..5f1e30a710f
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
@@ -0,0 +1,59 @@ 
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <atomic>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <type_traits>
+#include <chrono>
+
+#include <testsuite_hooks.h>
+
+int
+main ()
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic<bool> a(false);
+  std::atomic<bool> b(false);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(false);
+		  if (a.load())
+		    {
+		      b.store(true);
+		    }
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(true);
+  a.notify_one();
+  t.join();
+  VERIFY( b.load() );
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
new file mode 100644
index 00000000000..0249341055c
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.cc
@@ -0,0 +1,31 @@ 
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "atomic/wait_notify_util.h"
+
+int
+main ()
+{
+  struct S{ int i; };
+  check<S> check_s{S{0},S{42}};
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
new file mode 100644
index 00000000000..8531bb2e788
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/pointers.cc
@@ -0,0 +1,59 @@ 
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <atomic>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <type_traits>
+#include <chrono>
+
+#include <testsuite_hooks.h>
+
+int
+main ()
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  long aa;
+  long bb;
+
+  std::atomic<long*> a(nullptr);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(nullptr);
+		  if (a.load() == &aa)
+		    a.store(&bb);
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(&aa);
+  a.notify_one();
+  t.join();
+  VERIFY( a.load() == &bb);
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
new file mode 100644
index 00000000000..4f026e1dc9c
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_flag/wait_notify/1.cc
@@ -0,0 +1,61 @@ 
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <concepts>
+#include <mutex>
+#include <thread>
+
+#include <testsuite_hooks.h>
+
+int
+main()
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic_flag a;
+  std::atomic_flag b;
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(false);
+		  b.test_and_set();
+		  b.notify_one();
+		});
+
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.test_and_set();
+  a.notify_one();
+  b.wait(false);
+  t.join();
+
+  VERIFY( a.test() );
+  VERIFY( b.test() );
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
new file mode 100644
index 00000000000..b46eb603304
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_float/wait_notify.cc
@@ -0,0 +1,32 @@ 
+// { dg-options "-std=gnu++2a -pthread -latomic -L../../libatomic/.libs" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "atomic/wait_notify_util.h"
+
+int
+main ()
+{
+  check<float> f;
+  check<double> d;
+  check<long double> l;
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
new file mode 100644
index 00000000000..6e9ee7dbf93
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_integral/wait_notify.cc
@@ -0,0 +1,65 @@ 
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "atomic/wait_notify_util.h"
+
+void
+test01()
+{
+  struct S{ int i; };
+  std::atomic<S> s;
+
+  s.wait(S{42});
+}
+
+int
+main ()
+{
+  // check<bool> bb;
+  check<char> ch;
+  check<signed char> sch;
+  check<unsigned char> uch;
+  check<short> s;
+  check<unsigned short> us;
+  check<int> i;
+  check<unsigned int> ui;
+  check<long> l;
+  check<unsigned long> ul;
+  check<long long> ll;
+  check<unsigned long long> ull;
+
+  check<wchar_t> wch;
+  check<char8_t> ch8;
+  check<char16_t> ch16;
+  check<char32_t> ch32;
+
+  check<int8_t> i8;
+  check<int16_t> i16;
+  check<int32_t> i32;
+  check<int64_t> i64;
+
+  check<uint8_t> u8;
+  check<uint16_t> u16;
+  check<uint32_t> u32;
+  check<uint64_t> u64;
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
new file mode 100644
index 00000000000..1ced9d44b20
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic_ref/wait_notify.cc
@@ -0,0 +1,103 @@ 
+// { dg-options "-std=gnu++2a -pthread -latomic -L../../libatomic/.libs" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <atomic>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#include <chrono>
+#include <type_traits>
+
+#include <testsuite_hooks.h>
+
+template<typename Tp>
+Tp check_wait_notify(Tp val1, Tp val2)
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  Tp aa = val1;
+  std::atomic_ref<Tp> a(aa);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(val1);
+		  if (a.load() != val2)
+		    a = val1;
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(val2);
+  a.notify_one();
+  t.join();
+  return a.load();
+}
+
+template<typename Tp,
+	 bool = std::is_integral_v<Tp>
+	 || std::is_floating_point_v<Tp>>
+struct check;
+
+template<typename Tp>
+struct check<Tp, true>
+{
+  check()
+  {
+    Tp a = 0;
+    Tp b = 42;
+    VERIFY(check_wait_notify(a, b) == b);
+  }
+};
+
+template<typename Tp>
+struct check<Tp, false>
+{
+  check(Tp b)
+  {
+    Tp a;
+    VERIFY(check_wait_notify(a, b) == b);
+  }
+};
+
+struct foo
+{
+  long a = 0;
+  long b = 0;
+
+  foo& operator=(foo const&) = default;
+
+  friend bool
+  operator==(foo const& rhs, foo const& lhs)
+  { return rhs.a == lhs.a && rhs.b == lhs.b; }
+};
+
+int
+main ()
+{
+  check<long>();
+  check<double>();
+  check<foo>({42, 48});
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/latch/1.cc b/libstdc++-v3/testsuite/30_threads/latch/1.cc
new file mode 100644
index 00000000000..aa203cdf525
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/latch/1.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <latch>
+
+#ifndef __cpp_lib_latch
+# error "Feature-test macro for latch missing in <latch>"
+#elif __cpp_lib_latch!= 201907L
+# error "Feature-test macro for latch has wrong value in <latch>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/latch/2.cc b/libstdc++-v3/testsuite/30_threads/latch/2.cc
new file mode 100644
index 00000000000..318a859ee21
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/latch/2.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_latch
+# error "Feature-test macro for latch missing in <version>"
+#elif __cpp_lib_latch != 201907L
+# error "Feature-test macro for latch has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/latch/3.cc b/libstdc++-v3/testsuite/30_threads/latch/3.cc
new file mode 100644
index 00000000000..5d08000f430
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/latch/3.cc
@@ -0,0 +1,69 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+//
+#include <latch>
+#include <atomic>
+#include <thread>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+  std::latch l(3);
+
+  VERIFY( !l.try_wait() );
+
+  auto fn = [&]
+  {
+    l.count_down();
+  };
+
+  std::thread t0(fn);
+  std::thread t1(fn);
+
+  l.arrive_and_wait();
+  t0.join();
+  t1.join();
+
+  VERIFY( l.try_wait() );
+}
+
+void
+test02()
+{
+  std::latch l(3);
+  std::thread t([&]
+    {
+      l.count_down();
+    });
+
+  l.arrive_and_wait(2);
+  t.join();
+  VERIFY( l.try_wait() );
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/1.cc b/libstdc++-v3/testsuite/30_threads/semaphore/1.cc
new file mode 100644
index 00000000000..1bbca687fc3
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/1.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <semaphore>
+
+#ifndef __cpp_lib_semaphore
+# error "Feature-test macro for semaphore missing in <semaphore>"
+#elif __cpp_lib_semaphore != 201907L
+# error "Feature-test macro for semaphore has wrong value in <semaphore>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/2.cc b/libstdc++-v3/testsuite/30_threads/semaphore/2.cc
new file mode 100644
index 00000000000..98743f5e27c
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/2.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <version>
+
+#ifndef __cpp_lib_semaphore
+# error "Feature-test macro for semaphore missing in <version>"
+#elif __cpp_lib_semaphore != 201907L
+# error "Feature-test macro for semaphore has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
new file mode 100644
index 00000000000..d74cfad53e9
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
@@ -0,0 +1,30 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+#include <semaphore>
+
+int main()
+{
+  std::counting_semaphore<-1> sem(2);
+  return 0;
+}
+// { dg-error "static assertion failed" "" {  target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
new file mode 100644
index 00000000000..25280441d07
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
@@ -0,0 +1,55 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+#include <semaphore>
+#include <limits>
+#include <cstddef>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  std::counting_semaphore<10> s(3);
+
+  s.acquire();
+  VERIFY( s.try_acquire() );
+  VERIFY( s.try_acquire() );
+  VERIFY( !s.try_acquire() );
+  s.release();
+  VERIFY( s.try_acquire() );
+}
+
+void test02()
+{
+  std::binary_semaphore s(1);
+
+  s.acquire();
+  VERIFY( !s.try_acquire() );
+  s.release();
+  VERIFY( s.try_acquire() );
+}
+
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
new file mode 100644
index 00000000000..3f450e74661
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
@@ -0,0 +1,85 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+#include <semaphore>
+#include <chrono>
+#include <thread>
+#include <atomic>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std::chrono_literals;
+  std::counting_semaphore<10> s(2);
+  s.acquire();
+
+  auto const dur = 250ms;
+  {
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( s.try_acquire_for(dur) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff < dur );
+  }
+
+  {
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( !s.try_acquire_for(dur) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff >= dur );
+  }
+}
+
+void test02()
+{
+  using namespace std::chrono_literals;
+  std::binary_semaphore s(1);
+  std::atomic<int> a(0), b(0);
+  std::thread t([&] {
+    a.wait(0);
+    auto const dur = 250ms;
+    VERIFY( !s.try_acquire_for(dur) );
+    b++;
+    b.notify_one();
+
+    a.wait(1);
+    VERIFY( s.try_acquire_for(dur) );
+    b++;
+    b.notify_one();
+  });
+  t.detach();
+
+  s.acquire();
+  a++;
+  a.notify_one();
+  b.wait(0);
+  s.release();
+  a++;
+  a.notify_one();
+
+  b.wait(1);
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
new file mode 100644
index 00000000000..13bd7487d56
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
@@ -0,0 +1,153 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+#include <semaphore>
+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
+#include <chrono>
+#include <thread>
+#include <atomic>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std::chrono_literals;
+  std::__platform_semaphore s(2);
+  s._M_acquire();
+
+  auto const dur = 250ms;
+  {
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( s._M_try_acquire_for(dur) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff < dur );
+  }
+
+  {
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( !s._M_try_acquire_for(dur) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff >= dur );
+  }
+}
+
+void test02()
+{
+  using namespace std::chrono_literals;
+  std::__platform_semaphore s(1);
+  std::atomic<int> a(0), b(0);
+  std::thread t([&] {
+    a.wait(0);
+    auto const dur = 250ms;
+    VERIFY( !s._M_try_acquire_for(dur) );
+    b++;
+    b.notify_one();
+
+    a.wait(1);
+    VERIFY( s._M_try_acquire_for(dur) );
+    b++;
+    b.notify_one();
+  });
+  t.detach();
+
+  s._M_acquire();
+  a++;
+  a.notify_one();
+  b.wait(0);
+  s._M_release(1);
+  a++;
+  a.notify_one();
+
+  b.wait(1);
+}
+
+void test03()
+{
+  using namespace std::chrono_literals;
+  std::__platform_semaphore s(2);
+  s._M_acquire();
+
+  auto const dur = 250ms;
+  {
+    auto const at = std::chrono::system_clock::now() + dur;
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( s._M_try_acquire_until(at) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff < dur );
+  }
+
+  {
+    auto const at = std::chrono::system_clock::now() + dur;
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( !s._M_try_acquire_until(at) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff >= dur );
+  }
+}
+
+void test04()
+{
+  using namespace std::chrono_literals;
+  std::__platform_semaphore s(1);
+  std::atomic<int> a(0), b(0);
+  std::thread t([&] {
+    a.wait(0);
+    auto const dur = 250ms;
+    {
+      auto const at = std::chrono::system_clock::now() + dur;
+      VERIFY( !s._M_try_acquire_until(at) );
+
+      b++;
+      b.notify_one();
+    }
+
+    a.wait(1);
+    {
+      auto const at = std::chrono::system_clock::now() + dur;
+      VERIFY( s._M_try_acquire_until(at) );
+    }
+    b++;
+    b.notify_one();
+  });
+  t.detach();
+
+  s._M_acquire();
+  a++;
+  a.notify_one();
+  b.wait(0);
+  s._M_release(1);
+  a++;
+  a.notify_one();
+
+  b.wait(1);
+}
+#endif
+
+int main()
+{
+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  test01();
+  test02();
+  test03();
+  test04();
+#endif
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
new file mode 100644
index 00000000000..af7ab7bac39
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
@@ -0,0 +1,94 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a -pthread" }
+// { dg-do run { target c++2a } }
+// { dg-require-effective-target pthread }
+// { dg-require-gthreads "" }
+
+#include <semaphore>
+#include <chrono>
+#include <thread>
+#include <atomic>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+  using namespace std::chrono_literals;
+  std::counting_semaphore<10> s(2);
+  s.acquire();
+
+  auto const dur = 250ms;
+  {
+    auto const at = std::chrono::system_clock::now() + dur;
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( s.try_acquire_until(at) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff < dur );
+  }
+
+  {
+    auto const at = std::chrono::system_clock::now() + dur;
+    auto const t0 = std::chrono::steady_clock::now();
+    VERIFY( !s.try_acquire_until(at) );
+    auto const diff = std::chrono::steady_clock::now() - t0;
+    VERIFY( diff >= dur );
+  }
+}
+
+void test02()
+{
+  using namespace std::chrono_literals;
+  std::binary_semaphore s(1);
+  std::atomic<int> a(0), b(0);
+  std::thread t([&] {
+    a.wait(0);
+    auto const dur = 250ms;
+    {
+      auto const at = std::chrono::system_clock::now() + dur;
+      VERIFY( !s.try_acquire_until(at) );
+
+      b++;
+      b.notify_one();
+    }
+
+    a.wait(1);
+    {
+      auto const at = std::chrono::system_clock::now() + dur;
+      VERIFY( s.try_acquire_until(at) );
+    }
+    b++;
+    b.notify_one();
+  });
+  t.detach();
+
+  s.acquire();
+  a++;
+  a.notify_one();
+  b.wait(0);
+  s.release();
+  a++;
+  a.notify_one();
+
+  b.wait(1);
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h b/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h
new file mode 100644
index 00000000000..a319e8b60a6
--- /dev/null
+++ b/libstdc++-v3/testsuite/util/atomic/wait_notify_util.h
@@ -0,0 +1,160 @@ 
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <concepts>
+#include <mutex>
+#include <thread>
+
+#include <testsuite_hooks.h>
+
+#include <iostream>
+
+template<typename Tp>
+Tp check_wait_notify(Tp val1, Tp val2)
+  requires std::equality_comparable<Tp>
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic<Tp> a(val1);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(val1);
+		  if (a.load() != val2)
+		    a = val1;
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(val2);
+  a.notify_one();
+  t.join();
+  return a.load();
+}
+
+template<typename Tp>
+Tp check_wait_notify(Tp val1, Tp val2)
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic<Tp> a(val1);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  a.wait(val1);
+		  auto v = a.load();
+		  // TODO this needs to zero padding bits when we can do that
+		  if (__builtin_memcmp(&v, &val2, sizeof(Tp)) != 0)
+		    a = val1;
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(val2);
+  a.notify_one();
+  t.join();
+  return a.load();
+}
+
+template<typename Tp>
+Tp check_atomic_wait_notify(Tp val1, Tp val2)
+  requires std::equality_comparable<Tp>
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic<Tp> a(val1);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  std::atomic_wait(&a, val1);
+		  if (a.load() != val2)
+		    a = val1;
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(val2);
+  std::atomic_notify_one(&a);
+  t.join();
+  return a.load();
+}
+
+template<typename Tp>
+Tp check_atomic_wait_notify(Tp val1, Tp val2)
+{
+  using namespace std::literals::chrono_literals;
+
+  std::mutex m;
+  std::condition_variable cv;
+
+  std::atomic<Tp> a(val1);
+  std::thread t([&]
+		{
+		  cv.notify_one();
+		  std::atomic_wait(&a, val1);
+		  auto v = a.load();
+		  // TODO this needs to zero padding bits when we can do that
+		  if (__builtin_memcmp(&v, &val2, sizeof(Tp)) != 0)
+		    a = val1;
+		});
+  std::unique_lock<std::mutex> l(m);
+  cv.wait(l);
+  std::this_thread::sleep_for(100ms);
+  a.store(val2);
+  std::atomic_notify_one(&a);
+  t.join();
+  return a.load();
+}
+
+template<typename Tp>
+struct check
+{
+  check(Tp a = 0, Tp b = 42)
+  {
+    if constexpr (std::equality_comparable<Tp>)
+    {
+      VERIFY( check_wait_notify(a, b) == b);
+      VERIFY( check_atomic_wait_notify(a, b) == b);
+    }
+    else
+    {
+      {
+	// TODO this needs to zero padding bits when we can do that
+	auto v = check_wait_notify(a, b);
+	VERIFY( __builtin_memcmp(&v, &b, sizeof(Tp)) == 0 );
+      }
+
+      {
+	// TODO this needs to zero padding bits when we can do that
+	auto v = check_atomic_wait_notify(a, b);
+	VERIFY( __builtin_memcmp(&v, &b, sizeof(Tp)) == 0);
+      }
+    }
+  }
+};