diff mbox series

libstdc++: Add support for C++20 barriers

Message ID 20201217233706.3071964-1-rodgert@appliantology.com
State New
Headers show
Series libstdc++: Add support for C++20 barriers | expand

Commit Message

Thomas Rodgers Dec. 17, 2020, 11:37 p.m. UTC
From: Thomas Rodgers <trodgers@redhat.com>

Cleans up a few things mentioned on IRC.

Adds <barrier>

libstdc++/ChangeLog:

	* doc/doxygen/user.cfg.in: Add new header.
	* include/Makefile.am (std_headers): likewise.
	* include/Makefile.in: Regenerate.
        * include/precompiled/stdc++.h: Add new header.
	* include/std/barrier: New file.
	* include/std/version: Add __cpp_lib_barrier feature test macro.
	* testsuite/30_thread/barrier/1.cc: New test.
	* testsuite/30_thread/barrier/2.cc: Likewise.
	* testsuite/30_thread/barrier/arrive_and_drop.cc: Likewise.
	* testsuite/30_thread/barrier/arrive_and_wait.cc: Likewise.
	* testsuite/30_thread/barrier/arrive.cc: Likewise.
	* testsuite/30_thread/barrier/completion.cc: Likewise.
	* testsuite/30_thread/barrier/max.cc: Likewise.
---
 libstdc++-v3/doc/doxygen/user.cfg.in          |   1 +
 libstdc++-v3/include/Makefile.am              |   1 +
 libstdc++-v3/include/Makefile.in              |   1 +
 libstdc++-v3/include/precompiled/stdc++.h     |   1 +
 libstdc++-v3/include/std/barrier              | 249 ++++++++++++++++++
 libstdc++-v3/include/std/version              |   3 +
 .../testsuite/30_threads/barrier/1.cc         |  27 ++
 .../testsuite/30_threads/barrier/2.cc         |  27 ++
 .../testsuite/30_threads/barrier/arrive.cc    |  48 ++++
 .../30_threads/barrier/arrive_and_drop.cc     |  46 ++++
 .../30_threads/barrier/arrive_and_wait.cc     |  46 ++++
 .../30_threads/barrier/completion.cc          |  53 ++++
 .../testsuite/30_threads/barrier/max.cc       |  40 +++
 13 files changed, 543 insertions(+)
 create mode 100644 libstdc++-v3/include/std/barrier
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/1.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/2.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/completion.cc
 create mode 100644 libstdc++-v3/testsuite/30_threads/barrier/max.cc

Comments

Jonathan Wakely Dec. 18, 2020, 10:08 a.m. UTC | #1
On 17/12/20 15:37 -0800, Thomas Rodgers wrote:
>From: Thomas Rodgers <trodgers@redhat.com>
>
>Cleans up a few things mentioned on IRC.
>
>Adds <barrier>
>
>libstdc++/ChangeLog:
>
>	* doc/doxygen/user.cfg.in: Add new header.
>	* include/Makefile.am (std_headers): likewise.
>	* include/Makefile.in: Regenerate.
>        * include/precompiled/stdc++.h: Add new header.
>	* include/std/barrier: New file.
>	* include/std/version: Add __cpp_lib_barrier feature test macro.
>	* testsuite/30_thread/barrier/1.cc: New test.
>	* testsuite/30_thread/barrier/2.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive_and_drop.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive_and_wait.cc: Likewise.
>	* testsuite/30_thread/barrier/arrive.cc: Likewise.
>	* testsuite/30_thread/barrier/completion.cc: Likewise.
>	* testsuite/30_thread/barrier/max.cc: Likewise.


>+#ifndef _GLIBCXX_BARRIER
>+#define _GLIBCXX_BARRIER 1
>+
>+#pragma GCC system_header
>+
>+#if __cplusplus > 201703L
>+#include <bits/atomic_base.h>
>+#if __cpp_lib_atomic_wait  && __cpp_aligned_new

There's an extra space here before the && operator.

>+#endif // __cpp_lib_atomic_wait  && __cpp_aligned_new

And here.

>+#endif // __cplusplus > 201703L
>+#endif // _GLIBCXX_BARRIER
>+
>diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
>index e4a8bed52ab..07d17433c5b 100644
>--- a/libstdc++-v3/include/std/version
>+++ b/libstdc++-v3/include/std/version
>@@ -200,6 +200,9 @@
> #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
> # define __cpp_lib_atomic_wait 201907L
> #endif
>+#if __cpp_lib_atomic_wait

This needs to match the condition used in <barrier>.

>+#define __cpp_lib_barrier 201907L
>+#endif

You could just put it inside the previous block where
__cpp_lib_atomic_wait is defined:

#if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
# define __cpp_lib_atomic_wait 201907L
# if __cpp_aligned_new
#  define __cpp_lib_barrier 201907L
# endif
#endif

> #define __cpp_lib_bind_front 201907L
> #if __has_builtin(__builtin_bit_cast)
> # define __cpp_lib_bit_cast 201806L
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/1.cc b/libstdc++-v3/testsuite/30_threads/barrier/1.cc
>new file mode 100644
>index 00000000000..0b38160a58b
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/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 } }

This test will fail for non-gthreads targets, because they don't
define the macro. This needs the same condition as the similar
29_atomics/atomic/wait_notify/1.cc test:

// { dg-require-effective-target gthreads }

(which is the new way to say { dg-requires-gthread "" })

>+#include <barrier>
>+
>+#ifndef __cpp_lib_barrier
>+# error "Feature-test macro for barrier missing in <barrier>"
>+#elif __cpp_lib_barrier != 201907L
>+# error "Feature-test macro for barrier has wrong value in <barrier>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/2.cc b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>new file mode 100644
>index 00000000000..1d8d83639e0
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>@@ -0,0 +1,27 @@
>+// Copyright (C) 2019-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 } }

Same here.

>+#include <version>
>+
>+#ifndef __cpp_lib_barrier
>+# error "Feature-test macro for barrier missing in <version>"
>+#elif __cpp_lib_barrier != 201907L
>+# error "Feature-test macro for barrier has wrong value in <version>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>new file mode 100644
>index 00000000000..df70587db5b
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>@@ -0,0 +1,48 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive.pass.cpp

Please replace "implementation" with "test" or something like that,
since this isn't the implementation. Same for all the other tests
taken from LLVM.

>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  auto tok = b.arrive();
>+  std::thread t([&](){
>+    (void)b.arrive();
>+  });
>+  b.wait(std::move(tok));
>+  t.join();
>+
>+  auto tok2 = b.arrive(2);
>+  b.wait(std::move(tok2));
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>new file mode 100644
>index 00000000000..746a8f470e3
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>@@ -0,0 +1,46 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  std::thread t([&](){
>+    b.arrive_and_drop();
>+  });
>+
>+  b.arrive_and_wait();
>+  b.arrive_and_wait();
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>new file mode 100644
>index 00000000000..509986f3b78
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>@@ -0,0 +1,46 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp

Wrong filename?

>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  std::barrier<> b(2);
>+
>+  std::thread t([&](){
>+    for(int i = 0; i < 10; ++i)
>+      b.arrive_and_wait();
>+  });
>+  for(int i = 0; i < 10; ++i)
>+    b.arrive_and_wait();
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/completion.cc b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>new file mode 100644
>index 00000000000..c7997d9d7fb
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>@@ -0,0 +1,53 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }
>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/completion.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+#include <testsuite_hooks.h>
>+
>+int main(int, char**)
>+{
>+  int x = 0;
>+  auto comp = [&] { x += 1; };
>+  std::barrier<decltype(comp)> b(2, comp);
>+
>+  std::thread t([&](){
>+      for(int i = 0; i < 10; ++i)
>+	b.arrive_and_wait();
>+  });
>+
>+  for(int i = 0; i < 10; ++i)
>+    b.arrive_and_wait();
>+
>+  VERIFY( x == 10 );
>+  t.join();
>+}
>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/max.cc b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>new file mode 100644
>index 00000000000..278bc3fdd10
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>@@ -0,0 +1,40 @@
>+// { dg-options "-std=gnu++2a" }
>+// { dg-do run { target c++2a } }

This should be 'compile' not 'run'.

I think I'd rather see these static_asserts put into one of the
existing tests, so we don't pay for the overhead of another dejagnu
test (with all its setup and target checking) just for this.

Maybe in barrier/1.cc since that's not doing very much work either
(and don't forget to move the dg-additional-options there too).

>+// { dg-require-gthreads "" }
>+// { dg-additional-options "-pthread" { target pthread } }
>+
>+// 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/>.
>+
>+// This implementation is based on libcxx/test/std/thread/thread.barrier/max.pass.cpp
>+//===----------------------------------------------------------------------===//
>+//
>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>+// See https://llvm.org/LICENSE.txt for license information.
>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>+//
>+//===----------------------------------------------------------------------===//
>+
>+#include <barrier>
>+#include <thread>
>+
>+int main(int, char**)
>+{
>+  static_assert(std::barrier<>::max() > 0, "");
>+  auto l = [](){};
>+  static_assert(std::barrier<decltype(l)>::max() > 0, "");

No need for the string literals here, this is C++20.

OK with those changes, thanks.
Thomas Rodgers Jan. 7, 2021, 8:56 p.m. UTC | #2
Tested x86_64-pc-linux-gnu, committed to master.

Jonathan Wakely writes:

> On 17/12/20 15:37 -0800, Thomas Rodgers wrote:
>>From: Thomas Rodgers <trodgers@redhat.com>
>>
>>Cleans up a few things mentioned on IRC.
>>
>>Adds <barrier>
>>
>>libstdc++/ChangeLog:
>>
>>	* doc/doxygen/user.cfg.in: Add new header.
>>	* include/Makefile.am (std_headers): likewise.
>>	* include/Makefile.in: Regenerate.
>>        * include/precompiled/stdc++.h: Add new header.
>>	* include/std/barrier: New file.
>>	* include/std/version: Add __cpp_lib_barrier feature test macro.
>>	* testsuite/30_thread/barrier/1.cc: New test.
>>	* testsuite/30_thread/barrier/2.cc: Likewise.
>>	* testsuite/30_thread/barrier/arrive_and_drop.cc: Likewise.
>>	* testsuite/30_thread/barrier/arrive_and_wait.cc: Likewise.
>>	* testsuite/30_thread/barrier/arrive.cc: Likewise.
>>	* testsuite/30_thread/barrier/completion.cc: Likewise.
>>	* testsuite/30_thread/barrier/max.cc: Likewise.
>
>
>>+#ifndef _GLIBCXX_BARRIER
>>+#define _GLIBCXX_BARRIER 1
>>+
>>+#pragma GCC system_header
>>+
>>+#if __cplusplus > 201703L
>>+#include <bits/atomic_base.h>
>>+#if __cpp_lib_atomic_wait  && __cpp_aligned_new
>
> There's an extra space here before the && operator.
>
>>+#endif // __cpp_lib_atomic_wait  && __cpp_aligned_new
>
> And here.
>
>>+#endif // __cplusplus > 201703L
>>+#endif // _GLIBCXX_BARRIER
>>+
>>diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
>>index e4a8bed52ab..07d17433c5b 100644
>>--- a/libstdc++-v3/include/std/version
>>+++ b/libstdc++-v3/include/std/version
>>@@ -200,6 +200,9 @@
>> #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
>> # define __cpp_lib_atomic_wait 201907L
>> #endif
>>+#if __cpp_lib_atomic_wait
>
> This needs to match the condition used in <barrier>.
>
>>+#define __cpp_lib_barrier 201907L
>>+#endif
>
> You could just put it inside the previous block where
> __cpp_lib_atomic_wait is defined:
>
> #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
> # define __cpp_lib_atomic_wait 201907L
> # if __cpp_aligned_new
> #  define __cpp_lib_barrier 201907L
> # endif
> #endif
>
>> #define __cpp_lib_bind_front 201907L
>> #if __has_builtin(__builtin_bit_cast)
>> # define __cpp_lib_bit_cast 201806L
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/1.cc b/libstdc++-v3/testsuite/30_threads/barrier/1.cc
>>new file mode 100644
>>index 00000000000..0b38160a58b
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/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 } }
>
> This test will fail for non-gthreads targets, because they don't
> define the macro. This needs the same condition as the similar
> 29_atomics/atomic/wait_notify/1.cc test:
>
> // { dg-require-effective-target gthreads }
>
> (which is the new way to say { dg-requires-gthread "" })
>
>>+#include <barrier>
>>+
>>+#ifndef __cpp_lib_barrier
>>+# error "Feature-test macro for barrier missing in <barrier>"
>>+#elif __cpp_lib_barrier != 201907L
>>+# error "Feature-test macro for barrier has wrong value in <barrier>"
>>+#endif
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/2.cc b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>>new file mode 100644
>>index 00000000000..1d8d83639e0
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
>>@@ -0,0 +1,27 @@
>>+// Copyright (C) 2019-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 } }
>
> Same here.
>
>>+#include <version>
>>+
>>+#ifndef __cpp_lib_barrier
>>+# error "Feature-test macro for barrier missing in <version>"
>>+#elif __cpp_lib_barrier != 201907L
>>+# error "Feature-test macro for barrier has wrong value in <version>"
>>+#endif
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>>new file mode 100644
>>index 00000000000..df70587db5b
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
>>@@ -0,0 +1,48 @@
>>+// { dg-options "-std=gnu++2a" }
>>+// { dg-do run { target c++2a } }
>>+// { dg-require-gthreads "" }
>>+// { dg-additional-options "-pthread" { target pthread } }
>>+
>>+// 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/>.
>>+
>>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive.pass.cpp
>
> Please replace "implementation" with "test" or something like that,
> since this isn't the implementation. Same for all the other tests
> taken from LLVM.
>
>>+//===----------------------------------------------------------------------===//
>>+//
>>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>>+// See https://llvm.org/LICENSE.txt for license information.
>>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>+//
>>+//===----------------------------------------------------------------------===//
>>+
>>+#include <barrier>
>>+#include <thread>
>>+
>>+int main(int, char**)
>>+{
>>+  std::barrier<> b(2);
>>+
>>+  auto tok = b.arrive();
>>+  std::thread t([&](){
>>+    (void)b.arrive();
>>+  });
>>+  b.wait(std::move(tok));
>>+  t.join();
>>+
>>+  auto tok2 = b.arrive(2);
>>+  b.wait(std::move(tok2));
>>+}
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>>new file mode 100644
>>index 00000000000..746a8f470e3
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
>>@@ -0,0 +1,46 @@
>>+// { dg-options "-std=gnu++2a" }
>>+// { dg-do run { target c++2a } }
>>+// { dg-require-gthreads "" }
>>+// { dg-additional-options "-pthread" { target pthread } }
>>+
>>+// 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/>.
>>+
>>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
>>+//===----------------------------------------------------------------------===//
>>+//
>>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>>+// See https://llvm.org/LICENSE.txt for license information.
>>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>+//
>>+//===----------------------------------------------------------------------===//
>>+
>>+#include <barrier>
>>+#include <thread>
>>+
>>+int main(int, char**)
>>+{
>>+  std::barrier<> b(2);
>>+
>>+  std::thread t([&](){
>>+    b.arrive_and_drop();
>>+  });
>>+
>>+  b.arrive_and_wait();
>>+  b.arrive_and_wait();
>>+  t.join();
>>+}
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>>new file mode 100644
>>index 00000000000..509986f3b78
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
>>@@ -0,0 +1,46 @@
>>+// { dg-options "-std=gnu++2a" }
>>+// { dg-do run { target c++2a } }
>>+// { dg-require-gthreads "" }
>>+// { dg-additional-options "-pthread" { target pthread } }
>>+
>>+// 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/>.
>>+
>>+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
>
> Wrong filename?
>
>>+//===----------------------------------------------------------------------===//
>>+//
>>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>>+// See https://llvm.org/LICENSE.txt for license information.
>>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>+//
>>+//===----------------------------------------------------------------------===//
>>+
>>+#include <barrier>
>>+#include <thread>
>>+
>>+int main(int, char**)
>>+{
>>+  std::barrier<> b(2);
>>+
>>+  std::thread t([&](){
>>+    for(int i = 0; i < 10; ++i)
>>+      b.arrive_and_wait();
>>+  });
>>+  for(int i = 0; i < 10; ++i)
>>+    b.arrive_and_wait();
>>+  t.join();
>>+}
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/completion.cc b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>>new file mode 100644
>>index 00000000000..c7997d9d7fb
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
>>@@ -0,0 +1,53 @@
>>+// { dg-options "-std=gnu++2a" }
>>+// { dg-do run { target c++2a } }
>>+// { dg-require-gthreads "" }
>>+// { dg-additional-options "-pthread" { target pthread } }
>>+
>>+// 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/>.
>>+
>>+// This implementation is based on libcxx/test/std/thread/thread.barrier/completion.pass.cpp
>>+//===----------------------------------------------------------------------===//
>>+//
>>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>>+// See https://llvm.org/LICENSE.txt for license information.
>>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>+//
>>+//===----------------------------------------------------------------------===//
>>+
>>+#include <barrier>
>>+#include <thread>
>>+
>>+#include <testsuite_hooks.h>
>>+
>>+int main(int, char**)
>>+{
>>+  int x = 0;
>>+  auto comp = [&] { x += 1; };
>>+  std::barrier<decltype(comp)> b(2, comp);
>>+
>>+  std::thread t([&](){
>>+      for(int i = 0; i < 10; ++i)
>>+	b.arrive_and_wait();
>>+  });
>>+
>>+  for(int i = 0; i < 10; ++i)
>>+    b.arrive_and_wait();
>>+
>>+  VERIFY( x == 10 );
>>+  t.join();
>>+}
>>diff --git a/libstdc++-v3/testsuite/30_threads/barrier/max.cc b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>>new file mode 100644
>>index 00000000000..278bc3fdd10
>>--- /dev/null
>>+++ b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
>>@@ -0,0 +1,40 @@
>>+// { dg-options "-std=gnu++2a" }
>>+// { dg-do run { target c++2a } }
>
> This should be 'compile' not 'run'.
>
> I think I'd rather see these static_asserts put into one of the
> existing tests, so we don't pay for the overhead of another dejagnu
> test (with all its setup and target checking) just for this.
>
> Maybe in barrier/1.cc since that's not doing very much work either
> (and don't forget to move the dg-additional-options there too).
>
>>+// { dg-require-gthreads "" }
>>+// { dg-additional-options "-pthread" { target pthread } }
>>+
>>+// 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/>.
>>+
>>+// This implementation is based on libcxx/test/std/thread/thread.barrier/max.pass.cpp
>>+//===----------------------------------------------------------------------===//
>>+//
>>+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
>>+// See https://llvm.org/LICENSE.txt for license information.
>>+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
>>+//
>>+//===----------------------------------------------------------------------===//
>>+
>>+#include <barrier>
>>+#include <thread>
>>+
>>+int main(int, char**)
>>+{
>>+  static_assert(std::barrier<>::max() > 0, "");
>>+  auto l = [](){};
>>+  static_assert(std::barrier<decltype(l)>::max() > 0, "");
>
> No need for the string literals here, this is C++20.
>
> OK with those changes, thanks.
Jonathan Wakely Jan. 14, 2021, 2:26 p.m. UTC | #3
On 07/01/21 12:56 -0800, Thomas Rodgers via Libstdc++ wrote:
>
>Tested x86_64-pc-linux-gnu, committed to master.

The copyright years need updating. Pushed to master.
diff mbox series

Patch

diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 2261d572efb..fb90db65e55 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -850,6 +850,7 @@  INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \
                          include/any \
                          include/array \
                          include/atomic \
+                         include/barrier \
                          include/bit \
                          include/bitset \
                          include/charconv \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 958dfea5a98..231f7c3ec8f 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -30,6 +30,7 @@  std_headers = \
 	${std_srcdir}/any \
 	${std_srcdir}/array \
 	${std_srcdir}/atomic \
+	${std_srcdir}/barrier \
 	${std_srcdir}/bit \
 	${std_srcdir}/bitset \
 	${std_srcdir}/charconv \
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index 692fae76a42..424c0e277d1 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -134,6 +134,7 @@ 
 #endif
 
 #if __cplusplus > 201703L
+#include <barrier>
 #include <bit>
 #include <compare>
 #include <concepts>
diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier
new file mode 100644
index 00000000000..db514540e37
--- /dev/null
+++ b/libstdc++-v3/include/std/barrier
@@ -0,0 +1,249 @@ 
+// <barrier> -*- 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.
+
+// 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/>.
+
+// This implementation is based on libcxx/include/barrier
+//===-- barrier.h --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------===//
+
+/** @file include/barrier
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_BARRIER
+#define _GLIBCXX_BARRIER 1
+
+#pragma GCC system_header
+
+#if __cplusplus > 201703L
+#include <bits/atomic_base.h>
+#if __cpp_lib_atomic_wait  && __cpp_aligned_new
+#include <bits/functional_hash.h>
+#include <bits/std_thread.h>
+#include <bits/unique_ptr.h>
+
+#include <array>
+
+#define __cpp_lib_barrier 201907L
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  struct __empty_completion
+  {
+    _GLIBCXX_ALWAYS_INLINE void
+    operator()() noexcept
+    { }
+  };
+
+/*
+
+The default implementation of __tree_barrier is a classic tree barrier.
+
+It looks different from literature pseudocode for two main reasons:
+ 1. Threads that call into std::barrier functions do not provide indices,
+    so a numbering step is added before the actual barrier algorithm,
+    appearing as an N+1 round to the N rounds of the tree barrier.
+ 2. A great deal of attention has been paid to avoid cache line thrashing
+    by flattening the tree structure into cache-line sized arrays, that
+    are indexed in an efficient way.
+
+*/
+
+  enum class __barrier_phase_t : unsigned char { };
+
+  template<typename _CompletionF>
+    class __tree_barrier
+    {
+      using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>;
+      using __atomic_phase_const_ref_t = std::__atomic_ref<const __barrier_phase_t>;
+      static constexpr auto __phase_alignment =
+		      __atomic_phase_ref_t::required_alignment;
+
+      using __tickets_t = std::array<__barrier_phase_t, 64>;
+      struct alignas(64) /* naturally-align the heap state */ __state_t
+      {
+	alignas(__phase_alignment) __tickets_t __tickets;
+      };
+
+      ptrdiff_t _M_expected;
+      unique_ptr<__state_t[]> _M_state;
+      __atomic_base<ptrdiff_t> _M_expected_adjustment;
+      _CompletionF _M_completion;
+
+      alignas(__phase_alignment) __barrier_phase_t  _M_phase;
+
+      bool
+      _M_arrive(__barrier_phase_t __old_phase)
+      {
+	const auto __old_phase_val = static_cast<unsigned char>(__old_phase);
+	const auto __half_step =
+			   static_cast<__barrier_phase_t>(__old_phase_val + 1);
+	const auto __full_step =
+			   static_cast<__barrier_phase_t>(__old_phase_val + 2);
+
+	size_t __current_expected = _M_expected;
+	std::hash<std::thread::id>__hasher;
+	size_t __current = __hasher(std::this_thread::get_id())
+					  % ((_M_expected + 1) >> 1);
+
+	for (int __round = 0; ; ++__round)
+	  {
+	    if (__current_expected <= 1)
+		return true;
+	    size_t const __end_node = ((__current_expected + 1) >> 1),
+			 __last_node = __end_node - 1;
+	    for ( ; ; ++__current)
+	      {
+		if (__current == __end_node)
+		  __current = 0;
+		auto __expect = __old_phase;
+		__atomic_phase_ref_t __phase(_M_state[__current]
+						.__tickets[__round]);
+		if (__current == __last_node && (__current_expected & 1))
+		  {
+		    if (__phase.compare_exchange_strong(__expect, __full_step,
+						        memory_order_acq_rel))
+		      break;     // I'm 1 in 1, go to next __round
+		  }
+		else if (__phase.compare_exchange_strong(__expect, __half_step,
+						         memory_order_acq_rel))
+		  {
+		    return false; // I'm 1 in 2, done with arrival
+		  }
+		else if (__expect == __half_step)
+		  {
+		    if (__phase.compare_exchange_strong(__expect, __full_step,
+						        memory_order_acq_rel))
+		      break;    // I'm 2 in 2, go to next __round
+		  }
+	      }
+	    __current_expected = __last_node + 1;
+	    __current >>= 1;
+	  }
+      }
+
+    public:
+      using arrival_token = __barrier_phase_t;
+
+      static constexpr ptrdiff_t
+      max() noexcept
+      { return __PTRDIFF_MAX__; }
+
+      __tree_barrier(ptrdiff_t __expected, _CompletionF __completion)
+	  : _M_expected(__expected), _M_expected_adjustment(0),
+	    _M_completion(move(__completion)),
+	    _M_phase(static_cast<__barrier_phase_t>(0))
+      {
+	size_t const __count = (_M_expected + 1) >> 1;
+
+	_M_state = std::make_unique<__state_t[]>(__count);
+      }
+
+      [[nodiscard]] arrival_token
+      arrive(ptrdiff_t __update)
+      {
+	__atomic_phase_ref_t __phase(_M_phase);
+	const auto __old_phase = __phase.load(memory_order_relaxed);
+	const auto __cur = static_cast<unsigned char>(__old_phase);
+	for(; __update; --__update)
+	  {
+	    if(_M_arrive(__old_phase))
+	      {
+		_M_completion();
+		_M_expected += _M_expected_adjustment.load(memory_order_relaxed);
+		_M_expected_adjustment.store(0, memory_order_relaxed);
+		auto __new_phase = static_cast<__barrier_phase_t>(__cur + 2);
+		__phase.store(__new_phase, memory_order_release);
+		__phase.notify_all();
+	      }
+	  }
+	return __old_phase;
+      }
+
+      void
+      wait(arrival_token&& __old_phase) const
+      {
+	__atomic_phase_const_ref_t __phase(_M_phase);
+	auto const __test_fn = [=, this]
+	  {
+	    return __phase.load(memory_order_acquire) != __old_phase;
+	  };
+	std::__atomic_wait(&_M_phase, __old_phase, __test_fn);
+      }
+
+      void
+      arrive_and_drop()
+      {
+	_M_expected_adjustment.fetch_sub(1, memory_order_relaxed);
+	(void)arrive(1);
+      }
+    };
+
+  template<typename _CompletionF = __empty_completion>
+    class barrier
+    {
+      // Note, we may introduce a "central" barrier algorithm at some point
+      // for more space constrained targets
+      using __algorithm_t = __tree_barrier<_CompletionF>;
+      __algorithm_t _M_b;
+
+    public:
+      using arrival_token = typename __tree_barrier<_CompletionF>::arrival_token;
+
+      static constexpr ptrdiff_t
+      max() noexcept
+      { return __algorithm_t::max(); }
+
+      explicit barrier(ptrdiff_t __count,
+		       _CompletionF __completion = _CompletionF())
+	  : _M_b(__count, std::move(__completion))
+      { }
+
+      barrier(barrier const&) = delete;
+      barrier& operator=(barrier const&) = delete;
+
+      [[nodiscard]] arrival_token
+      arrive(ptrdiff_t __update = 1)
+      { return _M_b.arrive(__update); }
+
+      void
+      wait(arrival_token&& __phase) const
+      { _M_b.wait(std::move(__phase)); }
+
+      void
+      arrive_and_wait()
+      { wait(arrive()); }
+
+      void
+      arrive_and_drop()
+      { _M_b.arrive_and_drop(); }
+    };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif // __cpp_lib_atomic_wait  && __cpp_aligned_new
+#endif // __cplusplus > 201703L
+#endif // _GLIBCXX_BARRIER
+
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index e4a8bed52ab..07d17433c5b 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -200,6 +200,9 @@ 
 #if defined _GLIBCXX_HAS_GTHREADS || defined _GLIBCXX_HAVE_LINUX_FUTEX
 # define __cpp_lib_atomic_wait 201907L
 #endif
+#if __cpp_lib_atomic_wait
+#define __cpp_lib_barrier 201907L
+#endif
 #define __cpp_lib_bind_front 201907L
 #if __has_builtin(__builtin_bit_cast)
 # define __cpp_lib_bit_cast 201806L
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/1.cc b/libstdc++-v3/testsuite/30_threads/barrier/1.cc
new file mode 100644
index 00000000000..0b38160a58b
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/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 <barrier>
+
+#ifndef __cpp_lib_barrier
+# error "Feature-test macro for barrier missing in <barrier>"
+#elif __cpp_lib_barrier != 201907L
+# error "Feature-test macro for barrier has wrong value in <barrier>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/2.cc b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
new file mode 100644
index 00000000000..1d8d83639e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/2.cc
@@ -0,0 +1,27 @@ 
+// Copyright (C) 2019-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_barrier
+# error "Feature-test macro for barrier missing in <version>"
+#elif __cpp_lib_barrier != 201907L
+# error "Feature-test macro for barrier has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
new file mode 100644
index 00000000000..df70587db5b
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive.cc
@@ -0,0 +1,48 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// 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/>.
+
+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive.pass.cpp
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <barrier>
+#include <thread>
+
+int main(int, char**)
+{
+  std::barrier<> b(2);
+
+  auto tok = b.arrive();
+  std::thread t([&](){
+    (void)b.arrive();
+  });
+  b.wait(std::move(tok));
+  t.join();
+
+  auto tok2 = b.arrive(2);
+  b.wait(std::move(tok2));
+}
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
new file mode 100644
index 00000000000..746a8f470e3
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_drop.cc
@@ -0,0 +1,46 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// 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/>.
+
+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <barrier>
+#include <thread>
+
+int main(int, char**)
+{
+  std::barrier<> b(2);
+
+  std::thread t([&](){
+    b.arrive_and_drop();
+  });
+
+  b.arrive_and_wait();
+  b.arrive_and_wait();
+  t.join();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
new file mode 100644
index 00000000000..509986f3b78
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/arrive_and_wait.cc
@@ -0,0 +1,46 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// 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/>.
+
+// This implementation is based on libcxx/test/std/thread/thread.barrier/arrive_and_drop.pass.cpp
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <barrier>
+#include <thread>
+
+int main(int, char**)
+{
+  std::barrier<> b(2);
+
+  std::thread t([&](){
+    for(int i = 0; i < 10; ++i)
+      b.arrive_and_wait();
+  });
+  for(int i = 0; i < 10; ++i)
+    b.arrive_and_wait();
+  t.join();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/completion.cc b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
new file mode 100644
index 00000000000..c7997d9d7fb
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/completion.cc
@@ -0,0 +1,53 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// 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/>.
+
+// This implementation is based on libcxx/test/std/thread/thread.barrier/completion.pass.cpp
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <barrier>
+#include <thread>
+
+#include <testsuite_hooks.h>
+
+int main(int, char**)
+{
+  int x = 0;
+  auto comp = [&] { x += 1; };
+  std::barrier<decltype(comp)> b(2, comp);
+
+  std::thread t([&](){
+      for(int i = 0; i < 10; ++i)
+	b.arrive_and_wait();
+  });
+
+  for(int i = 0; i < 10; ++i)
+    b.arrive_and_wait();
+
+  VERIFY( x == 10 );
+  t.join();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/barrier/max.cc b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
new file mode 100644
index 00000000000..278bc3fdd10
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/barrier/max.cc
@@ -0,0 +1,40 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+// { dg-require-gthreads "" }
+// { dg-additional-options "-pthread" { target pthread } }
+
+// 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/>.
+
+// This implementation is based on libcxx/test/std/thread/thread.barrier/max.pass.cpp
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <barrier>
+#include <thread>
+
+int main(int, char**)
+{
+  static_assert(std::barrier<>::max() > 0, "");
+  auto l = [](){};
+  static_assert(std::barrier<decltype(l)>::max() > 0, "");
+}