[committed] libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817]

Christophe Lyon christophe.lyon@linaro.org
Tue Sep 29 11:51:51 GMT 2020


On Sat, 26 Sep 2020 at 21:42, Jonathan Wakely via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> Glibc 2.32 adds a global variable that says whether the process is
> single-threaded. We can use this to decide whether to elide atomic
> operations, as a more precise and reliable indicator than
> __gthread_active_p.
>
> This means that guard variables for statics and reference counting in
> shared_ptr can use less expensive, non-atomic ops even in processes that
> are linked to libpthread, as long as no threads have been created yet.
> It also means that we switch to using atomics if libpthread gets loaded
> later via dlopen (this still isn't supported in general, for other
> reasons).
>
> We can't use __libc_single_threaded to replace __gthread_active_p
> everywhere. If we replaced the uses of __gthread_active_p in std::mutex
> then we would elide the pthread_mutex_lock in the code below, but not
> the pthread_mutex_unlock:
>
>   std::mutex m;
>   m.lock();            // pthread_mutex_lock
>   std::thread t([]{}); // __libc_single_threaded = false
>   t.join();
>   m.unlock();          // pthread_mutex_unlock
>
> We need the lock and unlock to use the same "is threading enabled"
> predicate, and similarly for init/destroy pairs for mutexes and
> condition variables, so that we don't try to release resources that were
> never acquired.
>
> There are other places that could use __libc_single_threaded, such as
> _Sp_locker in src/c++11/shared_ptr.cc and locale init functions, but
> they can be changed later.
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/96817
>         * include/ext/atomicity.h (__gnu_cxx::__is_single_threaded()):
>         New function wrapping __libc_single_threaded if available.
>         (__exchange_and_add_dispatch, __atomic_add_dispatch): Use it.
>         * libsupc++/guard.cc (__cxa_guard_acquire, __cxa_guard_abort)
>         (__cxa_guard_release): Likewise.
>         * testsuite/18_support/96817.cc: New test.
>
> Tested powerpc64le-linux, with glibc 2.31 and 2.32. Committed to trunk.

Hi,

This patch introduced regressions on armeb-linux-gnueabhf:
--target armeb-none-linux-gnueabihf --with-cpu cortex-a9
    g++.dg/compat/init/init-ref2 cp_compat_x_tst.o-cp_compat_y_tst.o execute
    g++.dg/cpp2a/decomp1.C  -std=gnu++14 execution test
    g++.dg/cpp2a/decomp1.C  -std=gnu++17 execution test
    g++.dg/cpp2a/decomp1.C  -std=gnu++2a execution test
    g++.dg/init/init-ref2.C  -std=c++14 execution test
    g++.dg/init/init-ref2.C  -std=c++17 execution test
    g++.dg/init/init-ref2.C  -std=c++2a execution test
    g++.dg/init/init-ref2.C  -std=c++98 execution test
    g++.dg/init/ref15.C  -std=c++14 execution test
    g++.dg/init/ref15.C  -std=c++17 execution test
    g++.dg/init/ref15.C  -std=c++2a execution test
    g++.dg/init/ref15.C  -std=c++98 execution test
    g++.old-deja/g++.jason/pmf7.C  -std=c++98 execution test
    g++.old-deja/g++.mike/leak1.C  -std=c++14 execution test
    g++.old-deja/g++.mike/leak1.C  -std=c++17 execution test
    g++.old-deja/g++.mike/leak1.C  -std=c++2a execution test
    g++.old-deja/g++.mike/leak1.C  -std=c++98 execution test
    g++.old-deja/g++.other/init19.C  -std=c++14 execution test
    g++.old-deja/g++.other/init19.C  -std=c++17 execution test
    g++.old-deja/g++.other/init19.C  -std=c++2a execution test
    g++.old-deja/g++.other/init19.C  -std=c++98 execution test

and probably some (280) in libstdc++ tests: (I didn't bisect those):
    19_diagnostics/error_category/generic_category.cc execution test
    19_diagnostics/error_category/system_category.cc execution test
    20_util/scoped_allocator/1.cc execution test
    20_util/scoped_allocator/2.cc execution test
    20_util/scoped_allocator/construct_pair_c++2a.cc execution test
    20_util/to_address/debug.cc execution test
    20_util/variant/run.cc execution test

Christophe


More information about the Libstdc++ mailing list