On 05/06/20 17:29 -0700, Thomas Rodgers wrote:
diff --git a/libstdc++-v3/include/bits/semaphore_base.h 
b/libstdc++-v3/include/bits/semaphore_base.h
new file mode 100644
index 00000000000..f0c4235d91c
--- /dev/null
+++ b/libstdc++-v3/include/bits/semaphore_base.h
@@ -0,0 +1,272 @@
+// -*- 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>
+
+#if defined _POSIX_SEMAPHORES  && __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
+  template<ptrdiff_t __least_max_value>
+    struct __platform_semaphore
+    {

I think we want to delete the copy constructor and copy assignment
operator for this type and __atomic_semaphore.

+      using __clock_t = chrono::system_clock;
+
+      explicit __platform_semaphore(ptrdiff_t __count) noexcept
+      {
+       static_assert( __least_max_value <= SEM_VALUE_MAX, "");
+       auto __e = sem_init(&_M_semaphore, 0, __count);
+       if (__e)
+         std::terminate();

I don't think we should bother checking the return value. The failure
conditions are EINVAL if __count > SEM_VALUE_MAX, and ENOSYS if the
second argument is non-zero. Both conditions should be impossible.

+      }
+
+      ~__platform_semaphore()
+      {
+       auto __e = sem_destroy(&_M_semaphore);
+       if (__e)
+         std::terminate();

Likewise here. The only error condition is EINVAL, which is impossible
if _M_semaphore is a valid semaphore, which the constructor already
ensured.

If somehow _M_semaphore is invalid it means the user broke something
(e.g. by scribbling over *this) and we don't need to detect and handle
that case.

+      }
+
+      _GLIBCXX_ALWAYS_INLINE void
+      acquire() noexcept
+      {
+       auto __err = sem_wait(&_M_semaphore);
+       if (__err)
+         std::terminate();

What about the EINTR case where the wait is interrupted by a signal?
I think that should retry, but it shouldn't terminate.

+      template<typename _Duration>
+       bool
+       __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())
+         };
+
+         auto __err = sem_timedwait(&_M_semaphore, &__ts);
+         if (__err && (errno == ETIMEDOUT))
+             return false;
+         else if (__err)
+             std::terminate();

I think this needs to handle both EINTR and EINVAL:

       EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than 
or equal to 1000 million.

Alternatively, just return immediately without waiting for a time
before the epoch, i.e.  __abs_time < time_point<__clock_t>{}

Otherwise time_point(-20ns) will cause EINVAL and terminate.


+         return true;
+       }
+
+      template<typename _Clock, typename _Duration>
+       bool
+       try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) 
noexcept
+       {
+         if constexpr (std::is_same<__clock_t, _Clock>::value)
+           {
+             return __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 (__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
+       try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
+       { return try_acquire_until(__clock_t::now() + __rtime); }
+
+      template<typename _Clock, typename _Duration>
+       _GLIBCXX_ALWAYS_INLINE void
+       release(ptrdiff_t __update) noexcept
+       {
+         do
+           {
+             auto __err = sem_post(&_M_semaphore);
+             if (__err)
+               std::terminate();
+           } while (--__update);
+       }
+
+      private:
+       sem_t _M_semaphore;
+      };
+#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE
+
+    template<typename _Tp>
+      struct __atomic_semaphore
+      {

Do we want a static_assert(is_integral_v<_Tp>) or similar?

+       explicit __atomic_semaphore(_Tp __count)

Add noexcept?

+         : _M_a(__count)
+       { }
+
+       _GLIBCXX_ALWAYS_INLINE void
+       acquire() noexcept
+       {
+         auto const __pred = [this]
+           {
+             auto __old = __atomic_impl::load(&this->_M_a,
+                             memory_order::acquire);

Would it be simpler to just use a local atomic_ref to manipulate _M_a
here, and in the other members performing atomic ops on that member?

+             if (__old == 0)
+               return false;
+             return __atomic_impl::compare_exchange_strong(&this->_M_a,
+                       __old, __old - 1,
+                       memory_order::acquire,
+                       memory_order::release);
+           };
+         auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
+         __atomic_wait(&_M_a, __old, __pred);

Strictly speaking, this __atomic_wait would violate the "all accesses
to that object shall exclusively occur through those atomic_ref
instances" rule. But we know that it's actually OK because
__atomic_wait is only performing atomic ops on the same location.

+       }
+
+       bool
+       try_acquire() noexcept
+       {
+         auto __old = __atomic_impl::load(&_M_a, memory_order::acquire);
+         if (__old == 0)
+           return false;
+
+         return __atomic_spin([this, &__old]
+           {
+             return __atomic_impl::compare_exchange_weak(&this->_M_a,
+                       __old, __old - 1,
+                       memory_order::acquire,
+                       memory_order::release);
+           });
+       }
+
+       template<typename _Clock, typename _Duration>
+         _GLIBCXX_ALWAYS_INLINE bool
+         try_acquire_until(const chrono::time_point<_Clock, _Duration>& 
__atime) noexcept
+         {
+           auto const __pred = [this]
+             {
+               auto __old = __atomic_impl::load(&this->_M_a,
+                               memory_order::acquire);
+               if (__old == 0)
+                 return false;
+               return __atomic_impl::compare_exchange_strong(&this->_M_a,
+                               __old, __old - 1,
+                               memory_order::acquire,
+                               memory_order::release);
+             };
+
+           auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
+           return __atomic_wait_until(&_M_a, __old, __pred, __atime);
+       }
+
+      template<typename _Rep, typename _Period>
+       _GLIBCXX_ALWAYS_INLINE bool
+       try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept
+       {
+         auto const __pred = [this]
+           {
+             auto __old = __atomic_impl::load(&this->_M_a,
+                             memory_order::acquire);
+             if (__old == 0)
+               return false;
+             return  __atomic_impl::compare_exchange_strong(&this->_M_a,
+                             __old, __old - 1,
+                             memory_order::acquire,
+                             memory_order::release);
+           };
+
+         auto __old = __atomic_impl::load(&_M_a, memory_order_relaxed);
+         return __atomic_wait_for(&_M_a, __old, __pred, __rtime);
+       }
+
+      _GLIBCXX_ALWAYS_INLINE void
+      release(ptrdiff_t __update) noexcept
+      {
+       if (0 < __atomic_impl::fetch_add(&_M_a, __update, memory_order_release))
+         return;
+       if (__update > 1)
+         __atomic_impl::notify_all(&_M_a);
+       else
+         __atomic_impl::notify_one(&_M_a);
+      }
+
+    private:
+      alignas(__alignof__(_Tp)) _Tp _M_a;
+    };
+
+#ifdef _GLIBCXX_REQUIRE_POSIX_SEMAPHORE

What is this case for? This macro seems to only exist for use by a
single testcase.

Is it supposed to be something users can set? If so, it needs to be
documented as ABI-breaking and as implying that counting_semaphore
cannot be use with counts higher than SEM_VALUE_MAX.

+  template<ptrdiff_t __least_max_value>
+    using __semaphore_base = __platform_semaphore<__least_max_value>;
+#else
+#  ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+  template<ptrdiff_t __least_max_value>
+    using __semaphore_base = conditional_t<(
+                             __least_max_value >= 0

This condition is redundant, we already know that counting_semaphore
has checked the value is non-negative.

+                               && __least_max_value <= 
__detail::__platform_wait_max_value),
+                             __atomic_semaphore<__detail::__platform_wait_t>,
+                             __atomic_semaphore<ptrdiff_t>>;
+
+// __platform_semaphore
+#  elif defined _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  template<ptrdiff_t __least_max_value>
+    using __semaphore_base = conditional_t<(
+                             __least_max_value >= 0

Redundant condition again.

+                               && __least_max_value <= SEM_VALUE_MAX),
+                             __platform_semaphore<__least_max_value>,
+                             __atomic_semaphore<ptrdiff_t>>;
+#  else
+  template<ptrdiff_t __least_max_value>
+    using __semaphore_base = __atomic_semaphore<ptrdiff_t>;
+#  endif
+#endif
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic
index a455286a784..3f18774031d 100644
--- a/libstdc++-v3/include/std/atomic
+++ b/libstdc++-v3/include/std/atomic
@@ -163,6 +163,19 @@ _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
@@ -352,6 +365,19 @@ _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) noexcept
+    { _M_i.wait(__old, __m); }

This can't be right. _M_i is of type _Tp in std::atomic<_Tp>, it doesn't have a wait member function.

If this compiles it suggests there are no tests for these members on
the primary template, e.g. something like:

void
test01()
{
  struct S { int i; };
  std:::atomic<S> s;
  s.wait();
}

+
+    // TODO add const volatile overload
+
+    void notify_one() const noexcept
+    { _M_i.notify_one(); }
+
+    void notify_all() const noexcept
+    { _M_i.notify_all(); }
+#endif
+
    };
#undef _GLIBCXX20_INIT

@@ -590,6 +616,18 @@ _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
@@ -1342,6 +1380,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                                     memory_order_seq_cst);
    }

+
+#if __cplusplus > 201703L
+  template<typename _Tp>
+    inline void atomic_wait(const atomic<_Tp>* __a,

Newline after the return type.

+                           typename std::atomic<_Tp>::value_type __old) 
noexcept
+    { __a->wait(__old); }
+
+  template<typename _Tp>
+    inline void atomic_wait_explicit(const atomic<_Tp>* __a,

And here.

+                                    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..aa5299d9fdd
--- /dev/null
+++ b/libstdc++-v3/include/std/latch
@@ -0,0 +1,90 @@
+// <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
+    _GLIBCXX_ALWAYS_INLINE ptrdiff_t

I don't think we need _GLIBCXX_ALWAYS_INLINE here.

+    max() noexcept
+    { return __gnu_cxx::__numeric_traits<ptrdiff_t>::__max; }
+
+    constexpr explicit latch(ptrdiff_t __expected) : _M_a(__expected) { }

Add noexcept.

+
+    ~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);

It looks like this could use atomic_ref too, although there'd be less
benefit here.

+      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
+    {
+      auto const __old = __atomic_impl::load(&_M_a, memory_order::acquire);
+      __atomic_wait(&_M_a, __old, [this] { return this->try_wait(); });
+    }
+
+    _GLIBCXX_ALWAYS_INLINE void
+    arrive_and_wait(ptrdiff_t __update = 1)
+    {
+      count_down();
+      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..90cf3244647
--- /dev/null
+++ b/libstdc++-v3/include/std/semaphore
@@ -0,0 +1,86 @@
+// <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::__numeric_traits<ptrdiff_t>::__max>
+    class counting_semaphore
+    {
+      static_assert(__least_max_value >=0, "");

Add a space before the 0. Get rid of the empty string literal.

+
+      __semaphore_base<__least_max_value> _M_sem;

"base" seems a bit misleading here when it's a member not a base
class. Would __semaphore_impl be better?

+
+    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)

We can add noexcept here, since we know neither of the
__semaphore_base types will throw. If you envision alternative
implementations in future, then it would be futureproof to use
noexcept(noexcept(_M_sem.release(1)))

+      { _M_sem.release(__update); }
+
+      void acquire()

Same here.

+      { _M_sem.acquire(); }
+
+      bool try_acquire() noexcept
+      { return _M_sem.try_acquire(); }
+
+      template<class _Rep, class _Period>
+       bool try_acquire_for(const std::chrono::duration<_Rep, _Period>& 
__rel_time)

Newline after the return type (the line is too long otherwise).

This one can potentially throw because of the duration arithmetic on
_Rep objects.

+       { return _M_sem.try_acquire_for(__rel_time); }
+
+      template<class _Clock, class _Duration>
+       bool try_acquire_until(const std::chrono::time_point<_Clock, 
_Duration>& __abs_time)

Newline after the return type (I think it's still going to be too
long).

+       { return _M_sem.try_acquire_until(__abs_time); }
+    };
+
+ 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 c6bde2cfbda..f09da3344f7 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -189,6 +189,8 @@
#endif
#define __cpp_lib_type_identity 201806L
#define __cpp_lib_unwrap_ref 201811L
+#define __cpp_lib_semaphore 201907L
+#define __cpp_lib_latch 201907L

You're adding these macros in the freestanding section, and these
aren't freestanding headers. They need to be in the _GLIBCXX_HOSTED
block, and the macros need to be in alphabetical order.

#if _GLIBCXX_HOSTED
#undef __cpp_lib_array_constexpr
diff --git 
a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.cc 
b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.cc
new file mode 100644
index 00000000000..1ced9d44b20
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/atomic_refs.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/29_atomics/atomic/wait_notify/bool.cc 
b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/bool.cc
new file mode 100644
index 00000000000..b9fc063c66f
--- /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/floats.cc 
b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/floats.cc
new file mode 100644
index 00000000000..1d032085752
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/floats.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 "generic.h"
+
+int
+main ()
+{
+  check<float> f;
+  check<double> d;
+  check<long double> l;
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h 
b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h
new file mode 100644
index 00000000000..0da374ece87
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/generic.h
@@ -0,0 +1,88 @@
+// -*- C++ -*- header.

This isn't a header. I don't think this modeline should be here.

The test seems to be missing any dg-options, target selectors etc.

+// 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 <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;
+
+  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_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);
+                 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>
+struct check
+{
+  check()
+  {
+    Tp a = 0;
+    Tp b = 42;
+    VERIFY(check_wait_notify(a, b) == b);
+    VERIFY(check_atomic_wait_notify(a, b) == b);
+  }
+};
diff --git a/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc 
b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc
new file mode 100644
index 00000000000..2afd19a7d14
--- /dev/null
+++ b/libstdc++-v3/testsuite/29_atomics/atomic/wait_notify/integrals.cc
@@ -0,0 +1,56 @@
+// { 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 "generic.h"
+
+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/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/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..756727f33b3
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/latch/2.cc
@@ -0,0 +1,27 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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..10bb500d261
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/latch/3.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+//

Just 2020.

+// 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>
+
+int main()
+{
+  std::atomic<int> a(0);
+
+  std::latch l(3);
+
+  VERIFY( !l.try_wait() );
+
+  auto fn = [&]
+  {
+    ++a;
+    l.count_down();
+  };
+
+  std::thread t0(fn);
+  std::thread t1(fn);
+
+  l.arrive_and_wait();
+  t0.join();
+  t1.join();
+
+  VERIFY( l.try_wait() );
+}
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..b96b8a59c64
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/2.cc
@@ -0,0 +1,27 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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..1ac9d261ca5
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/least_max_value_neg.cc
@@ -0,0 +1,28 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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>
+
+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..d38cef86cfc
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire.cc
@@ -0,0 +1,55 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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..965554a3c28
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_for.cc
@@ -0,0 +1,85 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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_futex.cc 
b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_futex.cc
new file mode 100644
index 00000000000..5e05606e97f
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_futex.cc
@@ -0,0 +1,51 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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>
+
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+void test01()
+{
+  // the implementation optimizes for values of least_max_t that can fit
+  // in a futex, make sure we cover the case where least_max_t doesn't
+  auto constexpr least_max_t = std::numeric_limits<std::ptrdiff_t>::max();
+  std::counting_semaphore<least_max_t> s(3);
+
+  s.acquire();
+  VERIFY( s.try_acquire() );
+  VERIFY( s.try_acquire() );
+  VERIFY( !s.try_acquire() );
+  s.release();
+  VERIFY( s.try_acquire() );
+}
+
+#endif
+
+int main()
+{
+#ifdef _GLIBCXX_HAVE_LINUX_FUTEX
+  test01();
+#endif
+}
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..bf99fd3cf8f
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc
@@ -0,0 +1,169 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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>
+
+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  // The implementation supports posix as an implementation strategy
+  // make sure we cover that case
+#define _GLIBCXX_REQUIRE_POSIX_SEMAPHORE


This macro is defined too late to do anything. It would ned to be
defined before including <semaphore> to have any effect.

+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()
+{
+  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 test03()
+{
+  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);
+}
+
+void test04()
+{
+  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 test05()
+{
+  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);
+}
+#endif
+
+int main()
+{
+#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+#endif
+}
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..cc67c5c0bf0
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_until.cc
@@ -0,0 +1,94 @@
+// Copyright (C) 2019-2020 Free Software Foundation, Inc.

Just 2020.

+//
+// 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();
+}
--
2.26.2


Reply via email to