From 805f44b797bf23b1c2cd95ab8cd9c748c7bdb8ea Mon Sep 17 00:00:00 2001
From: Pauli <suokkos@gmail.com>
Date: Sat, 5 Nov 2016 17:33:20 +0200
Subject: [PATCH] libstdc++: Fix future header for targets without atomic int
 instructions

---
 libstdc++-v3/include/std/future            |  4 +---
 libstdc++-v3/libsupc++/eh_ptr.cc           | 28 ++++++++++++++++------------
 libstdc++-v3/libsupc++/exception           |  3 +--
 libstdc++-v3/libsupc++/exception_ptr.h     |  4 ----
 libstdc++-v3/libsupc++/nested_exception.cc |  2 --
 libstdc++-v3/libsupc++/nested_exception.h  |  4 ----
 6 files changed, 18 insertions(+), 27 deletions(-)

Index: gcc-6-6.2.0/src/libstdc++-v3/include/std/future
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/include/std/future
+++ gcc-6-6.2.0/src/libstdc++-v3/include/std/future
@@ -182,8 +182,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     future<__async_result_of<_Fn, _Args...>>
     async(_Fn&& __fn, _Args&&... __args);
 
-#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
-  && (ATOMIC_INT_LOCK_FREE > 1)
+#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
 
   /// Base class and enclosing scope.
   struct __future_base
@@ -1745,7 +1744,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #endif // _GLIBCXX_ASYNC_ABI_COMPAT
 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
-       // && ATOMIC_INT_LOCK_FREE
 
   // @} group futures
 _GLIBCXX_END_NAMESPACE_VERSION
Index: gcc-6-6.2.0/src/libstdc++-v3/libsupc++/eh_ptr.cc
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/libsupc++/eh_ptr.cc
+++ gcc-6-6.2.0/src/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -23,14 +23,12 @@
 // <http://www.gnu.org/licenses/>.
 
 #include <bits/c++config.h>
-#include <bits/atomic_lockfree_defines.h>
-
-#if ATOMIC_INT_LOCK_FREE > 1
 
 #define _GLIBCXX_EH_PTR_COMPAT
 
 #include <exception>
 #include <bits/exception_ptr.h>
+#include <ext/atomicity.h>
 #include "unwind-cxx.h"
 
 using namespace __cxxabiv1;
@@ -103,7 +101,9 @@ std::__exception_ptr::exception_ptr::_M_
     {
       __cxa_refcounted_exception *eh =
 	__get_refcounted_exception_header_from_obj (_M_exception_object);
-      __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
+      _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&eh->referenceCount);
+      __gnu_cxx::__atomic_add_dispatch(&eh->referenceCount, 1);
+      _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&eh->referenceCount);
     }
 }
 
@@ -114,11 +114,13 @@ std::__exception_ptr::exception_ptr::_M_
   if (_M_exception_object)
     {
       __cxa_refcounted_exception *eh =
-	__get_refcounted_exception_header_from_obj (_M_exception_object);
-      if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
+        __get_refcounted_exception_header_from_obj (_M_exception_object);
+      _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&eh->referenceCount);
+      if (__gnu_cxx::__exchange_and_add_dispatch(&eh->referenceCount, -1) == 1)
         {
-	  if (eh->exc.exceptionDestructor)
-	    eh->exc.exceptionDestructor (_M_exception_object);
+          _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&eh->referenceCount);
+          if (eh->exc.exceptionDestructor)
+            eh->exc.exceptionDestructor (_M_exception_object);
 
           __cxa_free_exception (_M_exception_object);
           _M_exception_object = 0;
@@ -219,8 +221,10 @@ __gxx_dependent_exception_cleanup(_Unwin
 
   __cxa_free_dependent_exception (dep);
 
-  if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
+  _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&header->referenceCount);
+  if (__gnu_cxx::__exchange_and_add_dispatch(&header->referenceCount, -1) == 1)
     {
+      _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&header->referenceCount);
       if (header->exc.exceptionDestructor)
 	header->exc.exceptionDestructor (header + 1);
 
@@ -238,7 +242,9 @@ std::rethrow_exception(std::exception_pt
 
   __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
   dep->primaryException = obj;
-  __atomic_add_fetch (&eh->referenceCount, 1,  __ATOMIC_ACQ_REL);
+  _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&eh->referenceCount);
+  __gnu_cxx::__atomic_add_dispatch(&eh->referenceCount, 1);
+  _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&eh->referenceCount);
 
   dep->unexpectedHandler = get_unexpected ();
   dep->terminateHandler = get_terminate ();
@@ -260,5 +266,3 @@ std::rethrow_exception(std::exception_pt
 }
 
 #undef _GLIBCXX_EH_PTR_COMPAT
-
-#endif
Index: gcc-6-6.2.0/src/libstdc++-v3/libsupc++/exception
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/libsupc++/exception
+++ gcc-6-6.2.0/src/libstdc++-v3/libsupc++/exception
@@ -35,7 +35,6 @@
 #pragma GCC visibility push(default)
 
 #include <bits/c++config.h>
-#include <bits/atomic_lockfree_defines.h>
 
 extern "C++" {
 
@@ -166,7 +165,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
 
 #pragma GCC visibility pop
 
-#if (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1)
+#if (__cplusplus >= 201103L)
 #include <bits/exception_ptr.h>
 #include <bits/nested_exception.h>
 #endif
Index: gcc-6-6.2.0/src/libstdc++-v3/libsupc++/exception_ptr.h
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/libsupc++/exception_ptr.h
+++ gcc-6-6.2.0/src/libstdc++-v3/libsupc++/exception_ptr.h
@@ -36,10 +36,6 @@
 #include <bits/c++config.h>
 #include <bits/exception_defines.h>
 
-#if ATOMIC_INT_LOCK_FREE < 2
-#  error This platform does not support exception propagation.
-#endif
-
 extern "C++" {
 
 namespace std 
Index: gcc-6-6.2.0/src/libstdc++-v3/libsupc++/nested_exception.cc
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/libsupc++/nested_exception.cc
+++ gcc-6-6.2.0/src/libstdc++-v3/libsupc++/nested_exception.cc
@@ -25,7 +25,5 @@
 
 namespace std 
 {
-#if ATOMIC_INT_LOCK_FREE > 1
   nested_exception::~nested_exception() noexcept = default;
-#endif
 } // namespace std
Index: gcc-6-6.2.0/src/libstdc++-v3/libsupc++/nested_exception.h
===================================================================
--- gcc-6-6.2.0.orig/src/libstdc++-v3/libsupc++/nested_exception.h
+++ gcc-6-6.2.0/src/libstdc++-v3/libsupc++/nested_exception.h
@@ -39,10 +39,6 @@
 #include <bits/c++config.h>
 #include <bits/move.h>
 
-#if ATOMIC_INT_LOCK_FREE < 2
-#  error This platform does not support exception propagation.
-#endif
-
 extern "C++" {
 
 namespace std
--- gcc-5.3.0.orig/src/libstdc++-v3/src/c++11/future.cc	2015-03-18 19:08:29.000000000 +0100
+++ gcc-5.3.0/src/libstdc++-v3/src/c++11/future.cc	2019-08-24 21:24:53.788069256 +0200
@@ -78,8 +78,7 @@
   const char*
   future_error::what() const noexcept { return logic_error::what(); }
 
-#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
-  && (ATOMIC_INT_LOCK_FREE > 1)
+#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) 
   __future_base::_Result_base::_Result_base() = default;
 
   __future_base::_Result_base::~_Result_base() = default;
