diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-11-27 23:25:56 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-11-27 23:25:56 +0000 |
commit | da29d2a36ef4bc2d6459267ce21ac932ddfbad6a (patch) | |
tree | cbf62faa339ce7361ab360531fd9149183d82752 /libstdc++-v3/configure | |
parent | b07b06716375f6bff210a828eddba1a3fd784d25 (diff) | |
download | gcc-da29d2a36ef4bc2d6459267ce21ac932ddfbad6a.tar.gz |
PR libstdc++/67843 set shared_ptr lock policy at build-time
This resolves a longstanding issue where the lock policy for shared_ptr
reference counting depends on compilation options when the header is
included, so that different -march options can cause ABI changes. For
example, objects compiled with -march=armv7 will use atomics to
synchronize reference counts, and objects compiled with -march=armv5t
will use a mutex. That means the shared_ptr control block will have a
different layout in different objects, causing ODR violations and
undefined behaviour. This was the root cause of PR libstdc++/42734 as
well as PR libstdc++/67843.
The solution is to decide on the lock policy at build time, when
libstdc++ is configured. The configure script checks for the
availability of the necessary atomic built-ins for the target and fixes
that choice permanently. Different -march flags used to compile user
code will not cause changes to the lock policy. This results in an ABI
change for certain compilations, but only where there was already an ABI
incompatibility between the libstdc++.so library and objects built with
an incompatible -march option. In general, this means a more stable ABI
that isn't silently altered when -march flags make addition atomic ops
available.
To force a target to use "atomic" or "mutex" the new configure option
--with-libstdcxx-lock-policy can be used.
In order to turn ODR violations into linker errors, the uses of
shared_ptr in filesystem directory iterators have been replaced
with __shared_ptr, and explicit instantiations are declared. This
ensures that object files using those types cannot link to libstdc++
libs unless they use the same lock policy.
PR libstdc++/67843
* acinclude.m4 (GLIBCXX_ENABLE_LOCK_POLICY): Add new macro
that defines _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY.
* config.h.in: Regenerate.
* configure: Regenerate.
* configure.ac: Use GLIBCXX_ENABLE_LOCK_POLICY.
* doc/xml/manual/configure.xml: Document new configure option.
* include/bits/fs_dir.h (directory_iterator): Use __shared_ptr
instead of shared_ptr.
(recursive_directory_iterator): Likewise.
(__shared_ptr<_Dir>): Add explicit instantiation declaration.
(__shared_ptr<recursive_directory_iterator::_Dir_stack>): Likewise.
* include/bits/shared_ptr_base.h (__allocate_shared, __make_shared):
Add default template argument for _Lock_policy template parameter.
* include/ext/concurrence.h (__default_lock_policy): Check macro
_GLIBCXX_HAVE_ATOMIC_LOCK_POLICY instead of checking if the current
target supports the builtins for compare-and-swap.
* src/filesystem/std-dir.cc (__shared_ptr<_Dir>): Add explicit
instantiation definition.
(__shared_ptr<recursive_directory_iterator::_Dir_stack>): Likewise.
(directory_iterator, recursive_directory_iterator): Use __make_shared
instead of make_shared.
From-SVN: r266533
Diffstat (limited to 'libstdc++-v3/configure')
-rwxr-xr-x | libstdc++-v3/configure | 94 |
1 files changed, 85 insertions, 9 deletions
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 39f83e239d7..77805e8680f 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -907,6 +907,7 @@ enable_libtool_lock enable_hosted_libstdcxx enable_libstdcxx_verbose enable_libstdcxx_pch +with_libstdcxx_lock_policy enable_cstdio enable_clocale enable_nls @@ -1652,6 +1653,9 @@ Optional Packages: --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-libstdcxx-lock-policy={atomic,mutex,auto} + synchronization policy for shared_ptr reference + counting [default=auto] --with-python-dir the location to install Python modules. This path is relative starting from the prefix. --with-gnu-ld assume the C compiler uses GNU ld default=no @@ -11840,7 +11844,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11843 "configure" +#line 11847 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11946,7 +11950,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11949 "configure" +#line 11953 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -15632,7 +15636,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 15635 "configure" +#line 15639 "configure" int main() { typedef bool atomic_type; @@ -15667,7 +15671,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15670 "configure" +#line 15674 "configure" int main() { typedef short atomic_type; @@ -15702,7 +15706,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15705 "configure" +#line 15709 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -15738,7 +15742,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15741 "configure" +#line 15745 "configure" int main() { typedef long long atomic_type; @@ -15815,11 +15819,83 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu + +# Check whether --with-libstdcxx-lock-policy was given. +if test "${with_libstdcxx_lock_policy+set}" = set; then : + withval=$with_libstdcxx_lock_policy; libstdcxx_atomic_lock_policy=$withval +else + libstdcxx_atomic_lock_policy=auto +fi + + + case "$libstdcxx_atomic_lock_policy" in + atomic|mutex|auto) ;; + *) as_fn_error $? "Invalid argument for --with-libstdcxx-lock-policy" "$LINENO" 5 ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lock policy for shared_ptr reference counts" >&5 +$as_echo_n "checking for lock policy for shared_ptr reference counts... " >&6; } + + if test x"$libstdcxx_atomic_lock_policy" = x"auto"; then + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ac_save_CXXFLAGS="$CXXFLAGS" + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #if ! defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 + # error "No 2-byte compare-and-swap" + #elif ! defined __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 + # error "No 4-byte compare-and-swap" + #endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + libstdcxx_atomic_lock_policy=atomic +else + libstdcxx_atomic_lock_policy=mutex +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + CXXFLAGS="$ac_save_CXXFLAGS" + fi + + if test x"$libstdcxx_atomic_lock_policy" = x"atomic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: atomic" >&5 +$as_echo "atomic" >&6; } + +$as_echo "#define HAVE_ATOMIC_LOCK_POLICY 1" >>confdefs.h + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: mutex" >&5 +$as_echo "mutex" >&6; } + fi + + + + # Fake what AC_TRY_COMPILE does, without linking as this is # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 15822 "configure" +#line 15898 "configure" int main() { _Decimal32 d1; @@ -15861,7 +15937,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 15864 "configure" +#line 15940 "configure" template<typename T1, typename T2> struct same { typedef T2 type; }; @@ -15895,7 +15971,7 @@ $as_echo "$enable_int128" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 15898 "configure" +#line 15974 "configure" template<typename T1, typename T2> struct same { typedef T2 type; }; |