diff mbox

[WIP] libstdc++: Make certain exceptions transaction_safe.

Message ID 1447530329.30181.50.camel@localhost.localdomain
State New
Headers show

Commit Message

Torvald Riegel Nov. 14, 2015, 7:45 p.m. UTC
The attached patch makes some exceptions transaction-safe, as require by
the Transactional Memory TS.  It has some rough edges, but I'm hoping I
can sort them out quickly using your feedback.  It only supports
logic_error and exception/bad_exception, but the other exceptions that
the TM TS specifies as transaction-safe basically require the same
support (notably, runtime_error is the same as logic_error, and their
subclasses don't add anything).

There are two things that complicate such support.  First, it seems
better to not rely on -fgnu-tm of libstdc++ code for now (or at least we
tried to avoid this so far).  Therefore, the transactional clones in
this patch are all manually instrumented (ie, the functions are C
functions with names matching the mangled names of the respective C++
functions, and the _ZGTt prefix signaling that they are txnal clones).

Second, exceptions still use a COW string internally, which cannot be
made transaction-safe with just compiler support because of the
reference counting implementation inside of COW strings, which uses
atomics.  One would need something custom for that nonetheless.

Thus, the patch adds txnal clones as required.  They are new exported
symbols, but not visible to nontransactional code.  The only changes to
headers is transaction_safe[_dynamic] annotations where required by the
TS, and a few friend declarations.  The annotaitons are only enabled if
a user compiles with -fgnu-tm.  IOW, the changes are pretty much
invisible when not using the TM TS.

The patch doesn't include tests yet, but tests like this one seem to run
successfully on x86_64:

template<typename T> void thrower4(const string& what)
{
  try
    {
      // Creating a temporary inside of the txn ICEs.
      T t(what);
      atomic_commit
      {
	_ITM_hackOrTxnProp (pr_atomicCancel);
	dontoptimize (t.what());
	throw T (what);
      }
    }
  catch (T ex)
    {
      if (what != ex.what()) abort ();
    }
}
thrower4<logic_error> ("test");

I can't yet test the destructors because of issues on the compiler side.
There are also commented-out calls to _ITM_setAssociatedException in the
code, which exist to show how we plan to support transaction
cancellation through exceptions (which needs some more libitm support
and bugfixes on the compiler side).

Comments

Jonathan Wakely Dec. 16, 2015, 9:05 p.m. UTC | #1
Sorry for the delay finishing this review, some of the code kept
melting my brain ;-)


On 14/11/15 20:45 +0100, Torvald Riegel wrote:
>diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
>index 1b3184a..d902b03 100644
>--- a/libstdc++-v3/config/abi/pre/gnu.ver
>+++ b/libstdc++-v3/config/abi/pre/gnu.ver
>@@ -1876,6 +1876,12 @@ GLIBCXX_3.4.22 {
>     _ZNSt6thread6_StateD[012]Ev;
>     _ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE;
> 
>+    # Support for the Transactional Memory TS (N4514)
>+    _ZGTtNSt11logic_errorC1EPKc;
>+    _ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
>+    _ZGTtNKSt11logic_error4whatEv;
>+    _ZGTtNSt11logic_errorD1Ev;
>+
> } GLIBCXX_3.4.21;

This is OK but ...

> # Symbols in the support library (libsupc++) have their own tag.
>@@ -2107,6 +2113,12 @@ CXXABI_1.3.9 {
>     # operator delete[](void*, std::size_t)
>     _ZdaPv[jmy];
> 
>+    # Support for the Transactional Memory TS (N4514)
>+    _ZGTtNKSt9exceptionD1Ev;
>+    _ZGTtNKSt9exception4whatEv;
>+    _ZGTtNKSt13bad_exceptionD1Ev;
>+    _ZGTtNKSt13bad_exception4whatEv;
>+
> } CXXABI_1.3.8;

That symbol version was already used in the gcc-5 release and so is
frozen, you'll need CXXABI_1.3.10 for these new symbols (similar to
https://gcc.gnu.org/ml/gcc-patches/2015-12/msg00258.html so if
Catherine's already added that version you can just add them there).


>diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
>index 723feb1..0e66bb0 100644
>--- a/libstdc++-v3/include/bits/c++config
>+++ b/libstdc++-v3/include/bits/c++config
>@@ -481,6 +481,17 @@ namespace std
> # define _GLIBCXX_BEGIN_EXTERN_C extern "C" {
> # define _GLIBCXX_END_EXTERN_C }
> 
>+// Conditionally enable annotations for the Transactional Memory TS on C++11.
>+#if __cplusplus >= 201103L && \
>+  _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_USE_DUAL_ABI && \

It's possible we can make this work for the old ABI too, but this is
OK for now. The old ABI always uses COW strings, but that's what the
code you've written deals with anyway.

>+  defined(__cpp_transactional_memory) && __cpp_transactional_memory >= 201505L

The defined(__cpp_transactional_memory) check is redundant, isn't it?

Users aren't allowed to define it, so it will either be defined to an
integer value or undefined and evaluate to zero.

>+#define _GLIBCXX_TXN_SAFE transaction_safe
>+#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic
>+#else
>+#define _GLIBCXX_TXN_SAFE
>+#define _GLIBCXX_TXN_SAFE_DYN
>+#endif
>+
> #else // !__cplusplus
> # define _GLIBCXX_BEGIN_EXTERN_C
> # define _GLIBCXX_END_EXTERN_C


>@@ -44,7 +46,36 @@ std::exception::what() const _GLIBCXX_USE_NOEXCEPT
> }
> 
> const char* 
>-std::bad_exception::what() const _GLIBCXX_USE_NOEXCEPT
>+std::bad_exception::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT
> {
>   return "std::bad_exception";
> }
>+
>+// Transactional clones for the destructors and what().
>+// what() is effectively transaction_pure, but we do not want to annotate it
>+// as such; thus, we call exactly the respective nontransactional function.
>+extern "C" {
>+
>+void
>+_ZGTtNKSt9exceptionD1Ev(const std::exception*)
>+{ }
>+
>+const char*
>+_ZGTtNKSt9exception4whatEv(const std::exception* that)
>+{
>+  return that->std::exception::what();
>+}

This makes a non-virtual call, is that correct?

If users derive from std::exception and override what() they will
expect a call to what() to dispatch to their override in the derived
class, but IIUC in a transactional block they would call this
function, which would call the base what(), not their override.

>+_ZGTtNKSt13bad_exception4whatEv(
>+    const std::bad_exception* that)
>+{
>+  return that->std::bad_exception::what();
>+}

Ditto.

>@@ -151,3 +164,220 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 
> _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace
>+
>+// Support for the Transactional Memory TS (N4514).
>+//
>+// logic_error and runtime_error both carry a message in the form of a COW
>+// string.  This COW string is never made visible to users of the exception
>+// because what() returns a C string.  The COW string can be constructed as
>+// either a copy of a COW string of another logic_error/runtime_error, or
>+// using a C string or SSO string; thus, the COW string's _Rep is only
>+// accessed by logic_error operations.  We control all txnal clones of those
>+// operations and thus can ensure that _Rep is never accessed transactionally.
>+// Furthermore, _Rep will always have been allocated or deallocated via
>+// global new or delete, so nontransactional writes we do to _Rep cannot

Hmm, will it always be global new/delete? It uses std::allocator,
which by default uses new/delete but libstdc++ can be configured to
use a different std::allocator implementation. If they always use new
at some point maybe we're OK, but I'd have to check the alternative
allocators. Maybe we just say only new_allocator is supported for TM.

I assume we want to avoid making a txnal std::allocator.

>+extern "C" {
>+
>+void
>+_ZGTtNSt11logic_errorC1EPKc (std::logic_error *that, const char* s)
>+{
>+  // This will use the singleton _Rep for an empty string and just point
>+  // to it instead of allocating memory.  Thus, we can use it as source, copy
>+  // it into the object we are constructing, and then construct the COW string
>+  // in the latter manually.
>+  std::logic_error le("");
>+  _ITM_memcpyRnWt(that, &le, sizeof(std::logic_error));
>+  _txnal_cow_string_C1_for_exceptions(_txnal_logic_error_get_msg(that),
>+				      s, that);

The shared empty _Rep is also only used conditionally, it can be
disabled with --enable-fully-dynamic-string. Maybe another thing we
just don't deal with for now.

Otherwise this looks good to me.
Jonathan Wakely Dec. 17, 2015, 8:04 p.m. UTC | #2
On 14/11/15 20:45 +0100, Torvald Riegel wrote:
>+void
>+_txnal_cow_string_D1(void *that)
>+{
>+  typedef std::basic_string<char> bs_type;
>+  bs_type::_Rep *rep = reinterpret_cast<bs_type::_Rep*>(
>+      const_cast<char*>(_txnal_cow_string_c_str(that))) - 1;
>+
>+  // The string can be shared, in which case we would need to decrement the
>+  // reference count.  We cannot undo that because we might loose the string
>+  // otherwise.  Therefore, we register a commit action that will dispose of
>+  // the string's _Rep.
>+  enum {_ITM_noTransactionId  = 1};
>+  _ITM_addUserCommitAction(_txnal_cow_string_D1_commit, _ITM_noTransactionId,
>+			   rep);
>+}

s/loose/lose/
diff mbox

Patch

commit e81080a01ab0daf2949a400c1a2d5077d37ba515
Author: Torvald Riegel <triegel@redhat.com>
Date:   Fri Nov 13 01:00:52 2015 +0100

    libstdc++: Make certain exceptions transaction_safe.

diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 1b3184a..d902b03 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1876,6 +1876,12 @@  GLIBCXX_3.4.22 {
     _ZNSt6thread6_StateD[012]Ev;
     _ZNSt6thread15_M_start_threadESt10unique_ptrINS_6_StateESt14default_deleteIS1_EEPFvvE;
 
+    # Support for the Transactional Memory TS (N4514)
+    _ZGTtNSt11logic_errorC1EPKc;
+    _ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+    _ZGTtNKSt11logic_error4whatEv;
+    _ZGTtNSt11logic_errorD1Ev;
+
 } GLIBCXX_3.4.21;
 
 # Symbols in the support library (libsupc++) have their own tag.
@@ -2107,6 +2113,12 @@  CXXABI_1.3.9 {
     # operator delete[](void*, std::size_t)
     _ZdaPv[jmy];
 
+    # Support for the Transactional Memory TS (N4514)
+    _ZGTtNKSt9exceptionD1Ev;
+    _ZGTtNKSt9exception4whatEv;
+    _ZGTtNKSt13bad_exceptionD1Ev;
+    _ZGTtNKSt13bad_exception4whatEv;
+
 } CXXABI_1.3.8;
 
 # Symbols in the support library (libsupc++) supporting transactional memory.
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index b3853cd..47d9f2f 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -4904,6 +4904,18 @@  _GLIBCXX_END_NAMESPACE_CXX11
       int
       compare(size_type __pos, size_type __n1, const _CharT* __s,
 	      size_type __n2) const;
+
+# ifdef _GLIBCXX_TM_TS_INTERNAL
+      friend void
+      ::_txnal_cow_string_C1_for_exceptions(void* that, const char* s,
+					    void* exc);
+      friend const char*
+      ::_txnal_cow_string_c_str(const void *that);
+      friend void
+      ::_txnal_cow_string_D1(void *that);
+      friend void
+      ::_txnal_cow_string_D1_commit(void *that);
+# endif
   };
 #endif  // !_GLIBCXX_USE_CXX11_ABI
 
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 723feb1..0e66bb0 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -481,6 +481,17 @@  namespace std
 # define _GLIBCXX_BEGIN_EXTERN_C extern "C" {
 # define _GLIBCXX_END_EXTERN_C }
 
+// Conditionally enable annotations for the Transactional Memory TS on C++11.
+#if __cplusplus >= 201103L && \
+  _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_USE_DUAL_ABI && \
+  defined(__cpp_transactional_memory) && __cpp_transactional_memory >= 201505L
+#define _GLIBCXX_TXN_SAFE transaction_safe
+#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic
+#else
+#define _GLIBCXX_TXN_SAFE
+#define _GLIBCXX_TXN_SAFE_DYN
+#endif
+
 #else // !__cplusplus
 # define _GLIBCXX_BEGIN_EXTERN_C
 # define _GLIBCXX_END_EXTERN_C
diff --git a/libstdc++-v3/include/std/stdexcept b/libstdc++-v3/include/std/stdexcept
index 2428919..620a2f4 100644
--- a/libstdc++-v3/include/std/stdexcept
+++ b/libstdc++-v3/include/std/stdexcept
@@ -117,11 +117,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   public:
     /** Takes a character string describing the error.  */
     explicit 
-    logic_error(const string& __arg);
+    logic_error(const string& __arg) _GLIBCXX_TXN_SAFE;
 
 #if __cplusplus >= 201103L
     explicit
-    logic_error(const char*);
+    logic_error(const char*) _GLIBCXX_TXN_SAFE;
 #endif
 
 #if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS
@@ -129,12 +129,16 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     logic_error& operator=(const logic_error&) _GLIBCXX_USE_NOEXCEPT;
 #endif
 
-    virtual ~logic_error() _GLIBCXX_USE_NOEXCEPT;
+    virtual ~logic_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
 
     /** Returns a C-style character string describing the general cause of
      *  the current error (the same string passed to the ctor).  */
     virtual const char* 
-    what() const _GLIBCXX_USE_NOEXCEPT;
+    what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
+# ifdef _GLIBCXX_TM_TS_INTERNAL
+    friend void*
+    ::_txnal_logic_error_get_msg(void* e);
+# endif
   };
 
   /** Thrown by the library, or by you, to report domain errors (domain in
diff --git a/libstdc++-v3/libsupc++/eh_exception.cc b/libstdc++-v3/libsupc++/eh_exception.cc
index 49f4632..cce813c 100644
--- a/libstdc++-v3/libsupc++/eh_exception.cc
+++ b/libstdc++-v3/libsupc++/eh_exception.cc
@@ -26,16 +26,18 @@ 
 #include "exception"
 #include <cxxabi.h>
 
-std::exception::~exception() _GLIBCXX_USE_NOEXCEPT { }
+std::exception::~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT { }
 
-std::bad_exception::~bad_exception() _GLIBCXX_USE_NOEXCEPT { }
+std::bad_exception::~bad_exception() _GLIBCXX_TXN_SAFE_DYN
+    _GLIBCXX_USE_NOEXCEPT
+{ }
 
 abi::__forced_unwind::~__forced_unwind() throw() { }
 
 abi::__foreign_exception::~__foreign_exception() throw() { }
 
 const char* 
-std::exception::what() const _GLIBCXX_USE_NOEXCEPT
+std::exception::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT
 {
   // NB: Another elegant option would be returning typeid(*this).name()
   // and not overriding what() in bad_exception, bad_alloc, etc.  In
@@ -44,7 +46,36 @@  std::exception::what() const _GLIBCXX_USE_NOEXCEPT
 }
 
 const char* 
-std::bad_exception::what() const _GLIBCXX_USE_NOEXCEPT
+std::bad_exception::what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT
 {
   return "std::bad_exception";
 }
+
+// Transactional clones for the destructors and what().
+// what() is effectively transaction_pure, but we do not want to annotate it
+// as such; thus, we call exactly the respective nontransactional function.
+extern "C" {
+
+void
+_ZGTtNKSt9exceptionD1Ev(const std::exception*)
+{ }
+
+const char*
+_ZGTtNKSt9exception4whatEv(const std::exception* that)
+{
+  return that->std::exception::what();
+}
+
+void
+_ZGTtNKSt13bad_exceptionD1Ev(
+    const std::bad_exception*)
+{ }
+
+const char*
+_ZGTtNKSt13bad_exception4whatEv(
+    const std::bad_exception* that)
+{
+  return that->std::bad_exception::what();
+}
+
+}
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index 5571fd9..e61975c 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -61,11 +61,12 @@  namespace std
   {
   public:
     exception() _GLIBCXX_USE_NOEXCEPT { }
-    virtual ~exception() _GLIBCXX_USE_NOEXCEPT;
+    virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
 
     /** Returns a C-style character string describing the general cause
      *  of the current error.  */
-    virtual const char* what() const _GLIBCXX_USE_NOEXCEPT;
+    virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN
+	_GLIBCXX_USE_NOEXCEPT;
   };
 
   /** If an %exception is thrown which is not listed in a function's
@@ -77,10 +78,11 @@  namespace std
 
     // This declaration is not useless:
     // http://gcc.gnu.org/onlinedocs/gcc-3.0.2/gcc_6.html#SEC118
-    virtual ~bad_exception() _GLIBCXX_USE_NOEXCEPT;
+    virtual ~bad_exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
 
     // See comment in eh_exception.cc.
-    virtual const char* what() const _GLIBCXX_USE_NOEXCEPT;
+    virtual const char* what() const _GLIBCXX_TXN_SAFE_DYN
+	_GLIBCXX_USE_NOEXCEPT;
   };
 
   /// If you write a replacement %terminate handler, it must be of this type.
diff --git a/libstdc++-v3/src/c++11/cow-stdexcept.cc b/libstdc++-v3/src/c++11/cow-stdexcept.cc
index d24dfe6..c14d5af 100644
--- a/libstdc++-v3/src/c++11/cow-stdexcept.cc
+++ b/libstdc++-v3/src/c++11/cow-stdexcept.cc
@@ -26,6 +26,19 @@ 
 // ISO C++ 14882: 19.1  Exception classes
 //
 
+// Enable hooks for support for the Transactional Memory TS (N4514).
+#define _GLIBCXX_TM_TS_INTERNAL
+void
+_txnal_cow_string_C1_for_exceptions(void* that, const char* s, void *exc);
+const char*
+_txnal_cow_string_c_str(const void *that);
+void
+_txnal_cow_string_D1(void *that);
+void
+_txnal_cow_string_D1_commit(void *that);
+void*
+_txnal_logic_error_get_msg(void* e);
+
 // All exception classes still use the classic COW std::string.
 #define _GLIBCXX_USE_CXX11_ABI 0
 #define _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS 1
@@ -151,3 +164,220 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
+
+// Support for the Transactional Memory TS (N4514).
+//
+// logic_error and runtime_error both carry a message in the form of a COW
+// string.  This COW string is never made visible to users of the exception
+// because what() returns a C string.  The COW string can be constructed as
+// either a copy of a COW string of another logic_error/runtime_error, or
+// using a C string or SSO string; thus, the COW string's _Rep is only
+// accessed by logic_error operations.  We control all txnal clones of those
+// operations and thus can ensure that _Rep is never accessed transactionally.
+// Furthermore, _Rep will always have been allocated or deallocated via
+// global new or delete, so nontransactional writes we do to _Rep cannot
+// interfere with transactional accesses.
+extern "C" {
+
+// Declare all libitm symbols we rely on, but make them weak so that we do
+// not depend on libitm.
+#define WEAK  __attribute__((weak))
+
+// FIXME copy over libitm's configury for MANGLE_SIZE_T?
+#define MANGLE_SIZE_T m
+#define CONCAT1(x,y)		x##y
+#define CONCAT(x,y)		CONCAT1(x,y)
+#define _ZGTtnaX		CONCAT(_ZGTtna,MANGLE_SIZE_T)
+
+#ifdef __i386__
+/* Only for 32-bit x86.  */
+# define ITM_REGPARM	__attribute__((regparm(2)))
+#else
+# define ITM_REGPARM
+#endif
+
+extern void *_ZGTtnaX (size_t sz)
+  _GLIBCXX_WEAK_DEFINITION;
+extern uint8_t _ITM_RU1(const uint8_t *p)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+extern uint32_t _ITM_RU4(const uint32_t *p)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+extern uint64_t _ITM_RU8(const uint64_t *p)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+extern void _ITM_memcpyRtWn(void *, const void *, size_t)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+extern void _ITM_memcpyRnWt(void *, const void *, size_t)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+extern void _ITM_addUserCommitAction(void (*)(void *), uint64_t, void *)
+  ITM_REGPARM _GLIBCXX_WEAK_DEFINITION;
+
+// If there is no support for weak, create dummies.
+// FIXME really needed for libstdc++?
+//#if !defined (HAVE_ELF_STYLE_WEAKREF)
+//void *_ZGTtnaX (size_t) { return NULL; }
+//uint8_t _ITM_RU1(const uint8_t *) { return 0; }
+//uint32_t _ITM_RU4(const uint32_t *) { return 0; }
+//uint64_t _ITM_RU8(const uint64_t *) { return 0; }
+//void _ITM_memcpyRtWn(void *, const void *, size_t) { }
+//void _ITM_memcpyRnWt(void *, const void *, size_t) { }
+//void _ITM_addUserCommitAction(void (*)(void *), uint64_t, void *) { };
+//#endif
+
+}
+
+// A transactional version of basic_string::basic_string(const char *s)
+// that also notifies the TM runtime about allocations belonging to this
+// exception.
+void
+_txnal_cow_string_C1_for_exceptions(void* that, const char* s, void *exc)
+{
+  typedef std::basic_string<char> bs_type;
+  bs_type *bs = (bs_type*) that;
+
+  // First, do a transactional strlen, but including the trailing zero.
+  bs_type::size_type len = 1;
+  for (const char *ss = s; _ITM_RU1((const uint8_t*) ss) != 0; ss++, len++);
+
+
+  // Allocate memory for the string and the refcount.  We use the
+  // transactional clone of global new[]; if this throws, it will do so in a
+  // transaction-compatible way.
+  // The allocation belongs to this exception, so tell the runtime about it.
+  // TODO associate exception
+//  void *prev = _ITM_setAssociatedException(exc);
+  bs_type::_Rep *rep;
+  try
+    {
+      rep = (bs_type::_Rep*) _ZGTtnaX (len + sizeof (bs_type::_Rep));
+    }
+  catch (...)
+    {
+      // Pop the association with this exception.
+//      _ITM_setAssociatedException(prev);
+      // We do not need to instrument a rethrow.
+      throw;
+    }
+  // Pop the association with this exception.
+//  _ITM_setAssociatedException(prev);
+
+  // Now initialize the rest of the string and copy the C string.  The memory
+  // will be freshly allocated, so nontransactional accesses are sufficient,
+  // including the writes when copying the string (see above).
+  rep->_M_set_sharable();
+  rep->_M_length = rep->_M_capacity = len - 1;
+  _ITM_memcpyRtWn(rep->_M_refdata(), s, len);
+  new (&bs->_M_dataplus) bs_type::_Alloc_hider(rep->_M_refdata(),
+					       bs_type::allocator_type());
+}
+
+static void* txnal_read_ptr(void* const * ptr)
+{
+  static_assert(sizeof(uint64_t) == sizeof(void*)
+		|| sizeof(uint32_t) == sizeof(void*));
+  // FIXME make a true compile-time choice to prevent warnings.
+  if (sizeof(uint64_t)== sizeof(void*))
+    return (void*)_ITM_RU8((const uint64_t*)ptr);
+  else
+    return (void*)_ITM_RU4((const uint32_t*)ptr);
+}
+
+// We must access the data pointer in the COW string transactionally because
+// another transaction can delete the string and reuse the memory.
+const char*
+_txnal_cow_string_c_str(const void *that)
+{
+  typedef std::basic_string<char> bs_type;
+  const bs_type *bs = (const bs_type*) that;
+
+  return (const char*) txnal_read_ptr((void**)&bs->_M_dataplus._M_p);
+}
+
+const char*
+_txnal_sso_string_c_str(const void *that)
+{
+  return (const char*) txnal_read_ptr(
+      (void* const*)const_cast<char* const*>(
+	  &((const std::__sso_string*) that)->_M_s._M_p));
+}
+
+void
+_txnal_cow_string_D1_commit(void *data)
+{
+  typedef std::basic_string<char> bs_type;
+  bs_type::_Rep *rep = (bs_type::_Rep*) data;
+  rep->_M_dispose(bs_type::allocator_type());
+}
+
+void
+_txnal_cow_string_D1(void *that)
+{
+  typedef std::basic_string<char> bs_type;
+  bs_type::_Rep *rep = reinterpret_cast<bs_type::_Rep*>(
+      const_cast<char*>(_txnal_cow_string_c_str(that))) - 1;
+
+  // The string can be shared, in which case we would need to decrement the
+  // reference count.  We cannot undo that because we might loose the string
+  // otherwise.  Therefore, we register a commit action that will dispose of
+  // the string's _Rep.
+  enum {_ITM_noTransactionId  = 1};
+  _ITM_addUserCommitAction(_txnal_cow_string_D1_commit, _ITM_noTransactionId,
+			   rep);
+}
+
+void*
+_txnal_logic_error_get_msg(void* e)
+{
+  std::logic_error* le = (std::logic_error*) e;
+  return &le->_M_msg;
+}
+
+extern "C" {
+
+void
+_ZGTtNSt11logic_errorC1EPKc (std::logic_error *that, const char* s)
+{
+  // This will use the singleton _Rep for an empty string and just point
+  // to it instead of allocating memory.  Thus, we can use it as source, copy
+  // it into the object we are constructing, and then construct the COW string
+  // in the latter manually.
+  std::logic_error le("");
+  _ITM_memcpyRnWt(that, &le, sizeof(std::logic_error));
+  _txnal_cow_string_C1_for_exceptions(_txnal_logic_error_get_msg(that),
+				      s, that);
+}
+// TODO C2 and C3?
+
+void
+_ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(
+    std::logic_error *that, const std::__sso_string& s)
+{
+  std::logic_error le("");
+  _ITM_memcpyRnWt(that, &le, sizeof(std::logic_error));
+  // This constructor is only declared transaction-safe if the C++11 ABI is
+  // used for std::string yet logic_error used a COW string internally.  A
+  // user must not call this constructor otherwise; although we can still
+  // compile and provide it, calling it would result in undefined behavior,
+  // which is in this case not initializing the message.
+#if _GLIBCXX_USE_DUAL_ABI
+  // Get the C string from the SSO string.
+  _txnal_cow_string_C1_for_exceptions(_txnal_logic_error_get_msg(that),
+				      _txnal_sso_string_c_str(&s), that);
+#endif
+}
+// TODO C2 and C3?
+
+const char*
+_ZGTtNKSt11logic_error4whatEv(const std::logic_error* that)
+{
+  return _txnal_cow_string_c_str(_txnal_logic_error_get_msg(
+      const_cast<std::logic_error*>(that)));
+}
+
+void
+_ZGTtNSt11logic_errorD1Ev(std::logic_error *that)
+{
+  _txnal_cow_string_D1(_txnal_logic_error_get_msg(that));
+}
+// TODO D0 and D2?
+
+}