Bug 64735 - std::future broken on armel
Summary: std::future broken on armel
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.9.2
: P3 normal
Target Milestone: 7.0
Assignee: Jonathan Wakely
URL:
Keywords:
: 58938 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-01-22 21:21 UTC by Bastiaan Jacques
Modified: 2017-01-18 17:25 UTC (History)
6 users (show)

See Also:
Host:
Target: arm
Build:
Known to work:
Known to fail: 4.9.0, 4.9.1, 4.9.2, 5.0
Last reconfirmed: 2015-01-23 00:00:00


Attachments
Not yet fully tested patch for std::future fix (1.89 KB, patch)
2016-11-05 22:07 UTC, Pauli
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Bastiaan Jacques 2015-01-22 21:21:36 UTC
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/armv5tel-unknown-linux-gnueabi/4.9.2/lto-wrapper
Target: armv5tel-unknown-linux-gnueabi
Configured with: /build/gcc/src/gcc-4.9-20141224/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://github.com/archlinuxarm/PKGBUILDs/issues --enable-languages=c,c++,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-cloog-backend=isl --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --disable-multilib --disable-werror --enable-checking=release --host=armv5tel-unknown-linux-gnueabi --build=armv5tel-unknown-linux-gnueabi --with-arch=armv5te --with-float=soft
Thread model: posix
gcc version 4.9.2 20141224 (prerelease) (GCC) 

Test case from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727621 :

#include <future>

int main()
{
        std::future<bool> fb = std::async([]{ return false; });
        return 0;
}

yields:

future.cc: In function ‘int main()’:
future.cc:5:27: error: variable ‘std::future<bool> fb’ has initializer but incomplete type
         std::future<bool> fb = std::async([]{ return false; });
                           ^
future.cc:5:62: error: invalid use of incomplete type ‘class std::future<bool>’
         std::future<bool> fb = std::async([]{ return false; });
                                                              ^
In file included from future.cc:1:0:
/usr/include/c++/4.9.2/future:114:11: error: declaration of ‘class std::future<bool>’
     class future;
           ^
/usr/include/c++/4.9.2/future: At global scope:
/usr/include/c++/4.9.2/future:176:5: error: ‘std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = main()::<lambda()>; _Args = {}; typename std::result_of<_Functor(_ArgTypes ...)>::type = bool]’, declared using local type ‘main()::<lambda()>’, is used but never defined [-fpermissive]
     async(_Fn&& __fn, _Args&&... __args);
     ^
Comment 1 Ramana Radhakrishnan 2015-01-23 10:01:35 UTC
Confirmed with -march=armv5te on all platforms. The only thing I can think of off the top of my head that is different for armv5te compared to armv7-a is that on armv5te we end up going through the kernel helper function for all atomic and sync type operations, there is no inlining and maybe that's what is broken in some sense here. 

Would help for some comments from a libstdc++ / C++ person.
Comment 2 Jonathan Wakely 2015-01-23 10:04:57 UTC
I think this is expected, the std:future type and std::async function are declared unconditionally, but the definitions are guarded by:

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
  && (ATOMIC_INT_LOCK_FREE > 1)

If your target doesn't meet those conditions then you don't get to use std::future
Comment 3 Jonathan Wakely 2015-01-23 10:05:38 UTC
i.e. it's not broken, it's missing, and that's by design.
Comment 4 Ramana Radhakrishnan 2015-01-23 10:25:40 UTC
(In reply to Jonathan Wakely from comment #3)
> i.e. it's not broken, it's missing, and that's by design.

Right so if I parse that correctly, it boils down to implementation of atomics with calls to kernel helper function vs the lack of it IIUC. Not really a libstdc++ issue but more of an issue with the way in which atomics are implemented on arch's that don't have the actual instruction support but are implemented through kernel helper functions.

It appears as though this breaks quite a few packages on older versions of the architecture so that's interesting.

Ramana
Comment 5 Bastiaan Jacques 2015-01-23 12:33:15 UTC
(In reply to Jonathan Wakely from comment #3)
> i.e. it's not broken, it's missing, and that's by design.

So is it the intention of the GCC developers that program writers targeting such platforms simply avoid these facilities and use std::thread/mutex instead?
Comment 6 Jonathan Wakely 2015-01-23 15:50:56 UTC
(In reply to Bastiaan Jacques from comment #5)
> (In reply to Jonathan Wakely from comment #3)
> > i.e. it's not broken, it's missing, and that's by design.
> 
> So is it the intention of the GCC developers that program writers targeting
> such platforms simply avoid these facilities and use std::thread/mutex
> instead?

Or they could contribute an implementation that works for their target.

The intention of the developers is that the feature should work correctly, and if that isn't possible with the current implementation for some target, then the feature should be disabled on that target. And that's what you see.
Comment 7 Pauli 2016-11-05 22:07:58 UTC
Created attachment 39971 [details]
Not yet fully tested patch for std::future fix

I'm currently in process fixing this bug. But I have to delay running tests and other verification for tomorrow. The patch is compile tested on Debian armel vm.
Comment 8 Jonathan Wakely 2016-11-07 22:27:00 UTC
The patch is a pessimization for non-armv5 targets, we don't want to change the targets that already work correctly. I'll look at a better way to do it (maybe encapsulating the ref-count more neatly) this week.
Comment 9 Pauli 2016-11-09 10:43:02 UTC
atomicity.h uses exactly same builtins if _GLIBCXX_ATOMIC_BUILTINS is set 1. Difference include check for __gthread_active_p check and annotations for race detector. Annotations are empty macros in default build. Same code is uses for all other atomic operations in libstdc++.

I'm finally having an working armv5te build from gcc-6-branch. I'm currently waiting the second unit test run to complete. If there is no unexpected failures from futures or exceptions I fill submit the complete patch later today.
Comment 10 Matthias Klose 2016-11-12 09:46:03 UTC
> I'm finally having an working armv5te build

is this supposed to work for armv4t as well?
Comment 11 Jonathan Wakely 2017-01-04 10:55:31 UTC
Author: redi
Date: Wed Jan  4 10:54:59 2017
New Revision: 244051

URL: https://gcc.gnu.org/viewcvs?rev=244051&root=gcc&view=rev
Log:
Support exception propagation without lock-free atomic int

2017-01-04  Pauli Nieminen  <suokkos@gmail.com>
	    Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/64735
	* acinclude.m4 (GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER): Define.
	* config.h.in: Regenerate.
	* config/abi/pre/gnu.ver [HAVE_EXCEPTION_PTR_SINCE_GCC46]
	(GLIBCXX_3.4.15, GLIBCXX_3.4.21, CXXABI_1.3.3, CXXABI_1.3.5): Make
	exports for exception_ptr, nested_exception, and future conditional.
	[HAVE_EXCEPTION_PTR_SINCE_GCC46] (GLIBCXX_3.4.23, CXXABI_1.3.11): Add
	exports for exception_ptr, nested_exception, and future conditional.
	* configure: Regenerate.
	* configure.ac: Use GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER.
	* include/std/future: Remove check for ATOMIC_INT_LOCK_FREE
	* libsupc++/eh_atomics.h: New file for internal use only.
	(__eh_atomic_inc, __eh_atomic_dec): New.
	* libsupc++/eh_ptr.cc (exception_ptr::_M_addref)
	(exception_ptr::_M_release) (__gxx_dependent_exception_cleanup)
	(rethrow_exception): Use eh_atomics.h reference counting helpers.
	* libsupc++/eh_throw.cc (__gxx_exception_cleanup): Likewise.
	* libsupc++/eh_tm.cc (free_any_cxa_exception): Likewise.
	* libsupc++/exception: Remove check for ATOMIC_INT_LOCK_FREE.
	* libsupc++/exception_ptr.h: Likewise.
	* libsupc++/guard.cc: Include header for ATOMIC_INT_LOCK_FREE macro.
	* libsupc++/nested_exception.cc: Remove check for
	ATOMIC_INT_LOCK_FREE.
	* libsupc++/nested_exception.h: Likewise.
	* src/c++11/future.cc: Likewise.
	* testsuite/18_support/exception_ptr/*: Remove atomic builtins checks.
	* testsuite/18_support/nested_exception/*: Likewise.
	* testsuite/30_threads/async/*: Likewise.
	* testsuite/30_threads/future/*: Likewise.
	* testsuite/30_threads/headers/future/types_std_c++0x.cc: Likewise.
	* testsuite/30_threads/packaged_task/*: Likewise.
	* testsuite/30_threads/promise/*: Likewise.
	* testsuite/30_threads/shared_future/*: Likewise.

Added:
    trunk/libstdc++-v3/libsupc++/eh_atomics.h
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/acinclude.m4
    trunk/libstdc++-v3/config.h.in
    trunk/libstdc++-v3/config/abi/pre/gnu.ver
    trunk/libstdc++-v3/configure
    trunk/libstdc++-v3/configure.ac
    trunk/libstdc++-v3/include/std/future
    trunk/libstdc++-v3/libsupc++/eh_ptr.cc
    trunk/libstdc++-v3/libsupc++/eh_throw.cc
    trunk/libstdc++-v3/libsupc++/eh_tm.cc
    trunk/libstdc++-v3/libsupc++/exception
    trunk/libstdc++-v3/libsupc++/exception_ptr.h
    trunk/libstdc++-v3/libsupc++/guard.cc
    trunk/libstdc++-v3/libsupc++/nested_exception.cc
    trunk/libstdc++-v3/libsupc++/nested_exception.h
    trunk/libstdc++-v3/src/c++11/future.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/62258.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/64241.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr_2.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/requirements.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/requirements_neg.cc
    trunk/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/51438.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/62154.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/68139.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/cons.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/nested_ptr.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_if_nested.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/rethrow_nested.cc
    trunk/libstdc++-v3/testsuite/18_support/nested_exception/throw_with_nested.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/42819.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/49668.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/54297.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/any.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/async.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/except.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/forced_unwind.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/launch.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/lwg2021.cc
    trunk/libstdc++-v3/testsuite/30_threads/async/sync.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/assign_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/constexpr.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/copy_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/default.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/move.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/cons/move_assign.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/45133.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/get.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/get2.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/share.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/valid.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/wait.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/wait_for.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/members/wait_until.cc
    trunk/libstdc++-v3/testsuite/30_threads/future/requirements/explicit_instantiation.cc
    trunk/libstdc++-v3/testsuite/30_threads/headers/future/types_std_c++0x.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/1.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/2.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/56492.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc2.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc_min.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/assign_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/copy_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/cons/move_assign.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/forced_unwind.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/at_thread_exit.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/get_future2.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke2.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke3.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke4.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/invoke5.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/reset2.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/swap.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/members/valid.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/requirements/explicit_instantiation.cc
    trunk/libstdc++-v3/testsuite/30_threads/packaged_task/uses_allocator.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/60966.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/69106.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/1.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/alloc2.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/alloc_min.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/assign_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/copy_neg.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/move.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/cons/move_assign.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/at_thread_exit.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/get_future.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/get_future2.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_exception.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_exception2.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value2.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/set_value3.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/members/swap.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/requirements/explicit_instantiation.cc
    trunk/libstdc++-v3/testsuite/30_threads/promise/uses_allocator.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/assign.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/constexpr.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/copy.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/default.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/move.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/cons/move_assign.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/45133.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/get.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/get2.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/valid.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/wait.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_for.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/members/wait_until.cc
    trunk/libstdc++-v3/testsuite/30_threads/shared_future/requirements/explicit_instantiation.cc
Comment 12 Jonathan Wakely 2017-01-04 10:57:25 UTC
This is fixed on trunk now, without pessimizing targets that already support exception propagation.
Comment 13 Jonathan Wakely 2017-01-18 17:25:16 UTC
*** Bug 58938 has been marked as a duplicate of this bug. ***