[PATCH] libstdc++: Add support for C++20 barriers

Jonathan Wakely jwakely@redhat.com
Thu Dec 17 14:06:26 GMT 2020


On 27/11/20 17:46 +0000, Jonathan Wakely wrote:
>On 20/11/20 16:30 -0800, Thomas Rodgers wrote:
>>From: Thomas Rodgers <trodgers@redhat.com>
>>
>>Should include all discussion on and off list to date.
>
>Most of the comments in
>https://gcc.gnu.org/pipermail/gcc-patches/2020-November/558090.html
>still apply to this version.
>
>>Adds <barrier>
>>
>>libstdc++/ChangeLog:
>>
>>	* include/Makefile.am (std_headers): Add new header.
>>	* include/Makefile.in: Regenerate.
>>	* 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/include/Makefile.am              |   1 +
>>libstdc++-v3/include/Makefile.in              |   1 +
>>libstdc++-v3/include/std/barrier              | 258 ++++++++++++++++++
>>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    |  51 ++++
>>.../30_threads/barrier/arrive_and_drop.cc     |  49 ++++
>>.../30_threads/barrier/arrive_and_wait.cc     |  51 ++++
>>.../30_threads/barrier/completion.cc          |  54 ++++
>>.../testsuite/30_threads/barrier/max.cc       |  44 +++
>>11 files changed, 566 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
>>
>>diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
>>index ca413b8fdfe..a20dd461fd1 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 \
>
>The new header should also be added to include/precompiled/stdc++.h
>and doc/doxygen/user.cfg.in
>
>>diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier
>>new file mode 100644
>>index 00000000000..a6cc6a058dd
>>--- /dev/null
>>+++ b/libstdc++-v3/include/std/barrier
>>@@ -0,0 +1,258 @@
>>+// <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
>>+//
>>+//===---------------------------------------------------------------===//
>
>This file doesn't have the usual @file doxygen block.
>
>>+
>>+#ifndef _GLIBCXX_BARRIER
>>+#define _GLIBCXX_BARRIER 1
>>+
>>+#pragma GCC system_header
>>+
>>+#if __cplusplus > 201703L
>>+#include <bits/c++config.h>
>>+
>>+#if defined(_GLIBCXX_HAS_GTHREADS)
>
>This doesn't match the condition used in <bits/atomic_wait.h>. I've
>added _GLIBCXX_HAVE_ATOMIC_WAIT so it could check that.
>
>>+#define __cpp_lib_barrier 201907L
>>+#include <bits/atomic_base.h>
>>+#include <bits/atomic_wait.h>
>
>This is already included by <bits/atomic_base.h>
>
>I suggest:
>
>#if __cplusplus > 201703L
>#include <bits/atomic_base.h>
>#ifdef _GLIBCXX_HAVE_ATOMIC_WAIT
>#include <bits/functional_hash.h>
>...
>#define __cpp_lib_barrier 201907L
>
>We should only define the __cpp_lib macro after including all other
>headers, otherwise we advertise to those headers that the feature
>exists, but it hasn't been defined yet. Nothing is trying to use
>barrier in the rest of the library yet, but that could change.
>
>>+#include <bits/functional_hash.h>
>>+
>>+#include <memory>
>>+
>>+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.
>>+
>>+*/
>>+
>>+  using __barrier_phase_t = uint8_t;
>>+
>>+  template<typename _CompletionF>
>>+    class __tree_barrier
>>+    {
>>+      struct alignas(64) /* naturally-align the heap state */ __state_t
>>+      {
>>+	struct
>>+	{
>>+	  __atomic_base<__barrier_phase_t> __phase = { 0 };
>>+	} __tickets[64];
>>+      };
>>+
>>+      ptrdiff_t _M_expected;
>>+      unique_ptr<char[]> _M_state_allocation;
>>+      __state_t* 		_M_state;
>>+      __atomic_base<ptrdiff_t> _M_expected_adjustment;
>>+      _CompletionF _M_completion;
>>+
>>+      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 size_t __phase_alignment =
>>+		      __atomic_phase_ref_t::required_alignment;
>>+      alignas(__phase_alignment) __barrier_phase_t  _M_phase;
>>+
>>+      static __gthread_t
>>+      _S_get_tid() noexcept
>>+      {
>>+#ifdef __GLIBC__
>>+	// For the GNU C library pthread_self() is usable without linking to
>>+	// libpthread.so but returns 0, so we cannot use it in single-threaded
>>+	// programs, because this_thread::get_id() != thread::id{} must be true.
>>+	// We know that pthread_t is an integral type in the GNU C library.
>>+	if (!__gthread_active_p())
>>+	  return 1;
>>+#endif
>>+	return __gthread_self();
>
>If you include <bits/std_thread.h> you can use this_thread::get_id()
>here. That avoids needing to repeat the glibc-specific hack.
>
>>+      }
>>+
>>+      bool
>>+      _M_arrive(__barrier_phase_t __old_phase)
>>+      {
>>+	__barrier_phase_t const __half_step = __old_phase + 1,
>>+				__full_step = __old_phase + 2;
>>+	size_t __current_expected = _M_expected;
>>+	size_t __current = _Hash_impl::hash(_S_get_tid())
>>+				% ((_M_expected + 1) >> 1);
>
>If we move std::hash<std::thread::id> into <bits/std_thread.h> then
>you can just use that.

Done in r11-6227.

Tested powerpc64le-linux, committed to trunk.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 2532 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-patches/attachments/20201217/041723b5/attachment.bin>


More information about the Gcc-patches mailing list