On Wed, 28 Nov 2018 at 00:25, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> 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.
>
> Tested x86_64-linux and aarch64-linux, committed to trunk.
>
> I would appreciate testing on ARM, especially Christophe's
> -march=armv5t set up.
>

Hi Jonathan,

Your patch passed my tests, thanks!
directory_iterator.cc tests used to be killed by a timeout until last
night where now they do PASS in my configurations involving
-march=armv5t.

That being said, I'm not sure I fully understand the fix. In my tests
involving -march=armv5t, I still configure GCC --with-cpu=cortex-a9,
and I pass -march=armv5t as an override with the --target-board runtest option.

In these cases libstdc++ configure detects support for "atomic", so I
suspect the tests pass only because I use QEMU with --cpu cortex-a9.
I think if I used a different QEMU cpu (eg arm926), the tests would
try to use atomics, and fail?

The reason I'm still using cortex-a9 at QEMU level is that many tests
override -mcpu/-march, and I used that as a compromise.

However, I do have configurations using --with-cpu=arm10tdmi or
--with-cpu=default and QEMU --cpu arm926.
In these 2 cases, the tests do PASS, but they used to before your
patch. libstdc++ configure does detect "mutex" in these cases.

To be hopefully clearer, the subset of relevant configurations I use
is as follows:
GCC target / with-cpu / RUNTEST target-board / QEMU cpu
1- arm-none-linux-gnueabi[hf]  / cortex-a9 / -march=armv5t / cortex-a9
2- arm-none-linux-gnueabihf / arm10tdmi / "" / arm926
3- arm-none-eabi / default / "" / arm926

(1) uses atomics
(2) and (3) use mutex

All of them now say "PASS", but maybe I should give a try switch to
arm926 for QEMU in (1) ?

Thanks,

Christophe

Reply via email to