Bug 58938 - std::exception_ptr is missing on architectures with incomplete atomic int support
Summary: std::exception_ptr is missing on architectures with incomplete atomic int sup...
Status: RESOLVED DUPLICATE of bug 64735
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: unknown
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-10-31 11:17 UTC by Rafał Rawicki
Modified: 2017-01-18 17:25 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-10-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rafał Rawicki 2013-10-31 11:17:43 UTC
In file ./libstdc++-v3/libsupc++/exception (also in trunk) bits/exception_ptr.h is included conditionally:

#if (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1)
#include <bits/exception_ptr.h>
#include <bits/nested_exception.h>
#endif

On ARM architecture ATOMIC_INT_LOCK_FREE is set to 1. That leads to losing some functionality of standard library for no good reason.
Comment 1 Paolo Carlini 2013-10-31 12:19:23 UTC
Was included conditionally before r181869 too, but the condition was different, checked _GLIBCXX_ATOMIC_BUILTINS_4 instead of ATOMIC_INT_LOCK_FREE > 1.
Comment 2 Jonathan Wakely 2013-10-31 13:10:53 UTC
So why is this a regression?  Does ARM define _GLIBCXX_ATOMIC_BUILTINS_4 but ATOMIC_INT_LOCK_FREE=1 ? That seems like a bug in those definitions.
Comment 3 Rafał Rawicki 2013-10-31 13:37:47 UTC
This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was defined (but is no longer available) and now there is defined ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no _GLIBCXX_ATOMIC_BUILTINS_8).

The other thing is, std::exception_ptr availability should not depend on the fact whether the platform has lock-free atomics or not.
Comment 4 Rafał Rawicki 2013-10-31 13:39:22 UTC
(In reply to Rafał Rawicki from comment #3)
> This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was
> defined (but is no longer available) and now there is defined
> ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because
> there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no
> _GLIBCXX_ATOMIC_BUILTINS_8).
> 
> The other thing is, std::exception_ptr availability should not depend on the
> fact whether the platform has lock-free atomics or not.

s/_GLIBCXX_ATOMIC_BUILTINS_4 was defined/_GLIBCXX_ATOMIC_BUILTINS_4 was used/
Comment 5 Paolo Carlini 2013-10-31 14:11:07 UTC
This is the relevant thread:

  http://gcc.gnu.org/ml/libstdc++/2011-11/msg00192.html

Let's add Andrew in CC.
Comment 6 Jonathan Wakely 2013-10-31 14:13:30 UTC
(In reply to Rafał Rawicki from comment #3)
> This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was
> defined (but is no longer available) and now there is defined
> ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because
> there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no
> _GLIBCXX_ATOMIC_BUILTINS_8).

But ATOMIC_INT_LOCK_FREE only refers to int, i.e. 4-byte integer, so if _GLIBCXX_ATOMIC_BUILTINS_4 was defined then I would expect atomic ops on int to always be lock-free, i.e. the macro should be defined to 2.  It's independent of whether atomic ops for 8-byte types are supported.

> The other thing is, std::exception_ptr availability should not depend on the
> fact whether the platform has lock-free atomics or not.

Without them you either need libatomic.so or you risk undefined behaviour such as  leaking exception objects or worse, dangling references to destroyed exceptions.
Comment 7 Andrew Macleod 2013-10-31 14:54:56 UTC
(In reply to Jonathan Wakely from comment #6)
> (In reply to Rafał Rawicki from comment #3)
> > This is a regression, because a more specific _GLIBCXX_ATOMIC_BUILTINS_4 was
> > defined (but is no longer available) and now there is defined
> > ATOMIC_INT_LOCK_FREE=1 (I think think the definition is correct, because
> > there were available _GLIBCXX_ATOMIC_BUILTINS_{1,2,4} and no
> > _GLIBCXX_ATOMIC_BUILTINS_8).
> 
> But ATOMIC_INT_LOCK_FREE only refers to int, i.e. 4-byte integer, so if
> _GLIBCXX_ATOMIC_BUILTINS_4 was defined then I would expect atomic ops on int
> to always be lock-free, i.e. the macro should be defined to 2.  It's
> independent of whether atomic ops for 8-byte types are supported.


yes. if an integer_type_node is 4 bytes, and the architecture has a 4 byte compare and swap, it should be set to 2 regardless of the lack of an 8 byte lock free operation.

this assert should never fail:
if (__atomic_always_lock_free(4, NULL) && (sizeof(int) == 4))
   assert (ATOMIC_INT_LOCK_FREE == 2);

In theory _GLIBCXX_ATOMIC_BUILTINS_4 should have been the same as ATOMIC_INT_LOCK_FREE as long as sizeof (int) == 4


> 
> > The other thing is, std::exception_ptr availability should not depend on the
> > fact whether the platform has lock-free atomics or not.
> 
> Without them you either need libatomic.so or you risk undefined behaviour
> such as  leaking exception objects or worse, dangling references to
> destroyed exceptions.
Comment 8 Paolo Carlini 2013-11-04 14:48:44 UTC
Closing then.
Comment 9 Rafał Rawicki 2013-11-04 15:44:15 UTC
I'm sorry about my confusion of ATOMIC_INT_LOCK_FREE and _GLIBCXX_ATOMIC_BUILTINS meaning.

In the meantime I've checked, when ATOMIC_INT_LOCK_FREE is defined as 2 and the target platform I have problems with (XScale, that is ARMv5), shouldn't have that defined. I'm still checking why I had _GLIBCXX_ATOMIC_BUILTINS_4 on gcc 4.6.

I would like to have the same codebase on all platforms and I wouldn't like to stop using std::exception_ptr. Jonathan Wakely wrote, that without hardware support I need libatomic.so or I'd have an undefined behaviour.

I do link with libatomic.so - does that mean, I can patch this conditional out (and similar conditional in the exception_ptr.h) and use exception_ptrs?

Why it was decided to remove a part of standard library instead of enforcing user to link with libatomic.so?
Comment 10 Jonathan Wakely 2013-11-04 16:22:07 UTC
(In reply to Rafał Rawicki from comment #9)
> I do link with libatomic.so - does that mean, I can patch this conditional
> out (and similar conditional in the exception_ptr.h) and use exception_ptrs?

You could try it.  I don't know if it will work correctly.

> Why it was decided to remove a part of standard library instead of enforcing
> user to link with libatomic.so?

That's the usual policy for the library, we don't define components that rely on features that are missing from target platforms.
Comment 11 frankhb1989 2014-10-31 20:23:37 UTC
I'd like to say it should be a bug, if I did not get it wrong.
Even for a freestanding implementation, ISO C++11 explicitly specified <exception> as one of required header in table 16, and it should meet the same requirements as for a hosted implementation. Missing exception propagation is definitely not conforming, whether it can actually be implemented or not.
Moreover, the standard doesn't specify anything about atomic operations on exception propagation, though it does requires that there should be no data race during some operations. Atomic operations here seem to be purely implementation details. Can it be implemented with something like __shared_ptr's lock policy?
This issue also has effect on nested exceptions. Anyway, I feel something indeed wrong when I have to miss std::nested_exception for this reason on a platform which has even no multithreading support at all (as allowed by C++11). Sigh.
BTW, libstdc++ manual Table 1.2 just tell me 'Y' for 18.8.5 and 18.8.6. Found no other notes about this issue. So at least it can be a defect of documentation.
Comment 12 Jonathan Wakely 2014-10-31 20:48:19 UTC
Someone just needs to do the work to support it on other targets.

One option would be to require libatomic, another would be to not use atomics at all if e.g. !defined(__GTHREADS)
Comment 13 Philip Deegan 2015-12-08 14:25:30 UTC
How would one fix this on ARMv7-A for instance? 

Compiling with "-march=armv7-a" on arm-linux-gnueabihf results in a link error for exception_ptr/current_exception/rethrow_exception etc.

gcc_5.3_ARM32HF/bin/gcc  -dM - -E -march=armv7-a < /dev/null | grep  ATOMIC_INT_LOCK_FREE
#define __GCC_ATOMIC_INT_LOCK_FREE 2
Comment 14 Jonathan Wakely 2015-12-08 14:38:08 UTC
(In reply to Philip Deegan from comment #13)
> How would one fix this on ARMv7-A for instance? 
> 
> Compiling with "-march=armv7-a" on arm-linux-gnueabihf results in a link
> error for exception_ptr/current_exception/rethrow_exception etc.
> 
> gcc_5.3_ARM32HF/bin/gcc  -dM - -E -march=armv7-a < /dev/null | grep 
> ATOMIC_INT_LOCK_FREE
> #define __GCC_ATOMIC_INT_LOCK_FREE 2

Did you try linking with -latomic ?
Comment 15 Philip Deegan 2015-12-08 15:10:09 UTC
Hi, thanks for the quick reply.

Yeah I tried with atomic, not much different shared or static, is something special required when building gcc/libc? 

Linking with --verbose results in:
-lmy_lib -latomic -lstdc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc /opt/gcc_5.3_ARM32HF/lib/gcc/arm-linux-gnueabihf/5.3.0/crtend.o

I'm happy to open another ticket/take this somewhere else.
Comment 16 Jonathan Wakely 2015-12-08 15:53:16 UTC
It should work if you build GCC for ARMv7, i.e. configure --with-arch=armv7-a, but that changes the instruction set used for all the target libraries.
Comment 17 Philip Deegan 2015-12-08 19:23:17 UTC
Building bin-utils/gcc/glibc with --with-arch=armv7-a did the trick.

Atomic is not required.

However, if a thread calls std::current_exception it segfaults in libstdc++-v3/libsupc++/eh_ptr.cc line 190:
__cxa_exception *header = globals->caughtExceptions;

Can only test static pthread linking currently with Wl,--whole-archive -lpthread -Wl,--no-whole-archive
Comment 18 Jonathan Wakely 2015-12-08 19:35:07 UTC
(In reply to Philip Deegan from comment #17)
> However, if a thread calls std::current_exception it segfaults in
> libstdc++-v3/libsupc++/eh_ptr.cc line 190:
> __cxa_exception *header = globals->caughtExceptions;
> 
> Can only test static pthread linking currently with Wl,--whole-archive
> -lpthread -Wl,--no-whole-archive

Please file a new bug for that, thanks.
Comment 19 Jonathan Wakely 2016-09-23 15:59:03 UTC
A prototype implementation that doesn't rely on atomics:

https://gcc.gnu.org/ml/gcc-patches/2016-09/msg01526.html
https://gcc.gnu.org/ml/gcc-patches/2016-09/msg01546.html
(both patches are needed).
Comment 20 Jonathan Wakely 2017-01-18 17:25:16 UTC
Fixed by the changes for PR 64735

*** This bug has been marked as a duplicate of bug 64735 ***