gcc/libstdc++-v3/libsupc++/guard.cc

461 lines
13 KiB
C++
Raw Normal View History

2022-01-03 17:42:10 +08:00
// Copyright (C) 2002-2022 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
// GCC is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3, or (at your option)
// any later version.
// GCC is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
// Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
#include <bits/c++config.h>
#include <cxxabi.h>
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#include <exception>
#include <new>
atomicity.h: Move to... 2006-09-13 Benjamin Kosnik <bkoz@redhat.com> * include/bits/atomicity.h: Move to... * include/ext/atomicity.h: ...here. * include/bits/concurrence.h: Move to... * include/ext/concurrence.h: ...here. * include/Makefile.am (ext_headers): Additions. (bits_headers): Subtractions. * include/Makefile.in: Regenerate. * include/ext/bitmap_allocator.h (_Mutex), __threads_enabled, _Lock, _Auto_Lock): Subsume into... * include/bits/concurrence.h (__mutex): ..this. Error check locking and unlocking. (lock): Uglify to... (__scoped_lock): Use __mutex. (__glibcxx_mutex_define_initialized): Remove. (__glibcxx_mutex_type): Remove. * include/tr1/boost_shared_ptr.h: Formating tweaks, adjustments. (_Lock_policy): Move from here... * include/ext/concurrence.h: ... to here. (__shared_ptr_default_lock_mode): To __default_lock_policy. (_S_lockfree): To _S_atomic. Document. * libsupc++/guard.cc (static_mutex): Subsume into and fixup for... * include/ext/concurrence.h (__recursive_mutex): ...this. Error check locking and unlocking. * libsupc++/eh_alloc.cc: Use __scoped_lock. * config/os/aix/atomicity.h: Fixups for include paths, mutex to __scoped_mutex change, removal of locking defines. * config/os/irix/atomicity.h: Same. * config/cpu/cris/atomicity.h: Same. * config/cpu/m68k/atomicity.h: Same. * config/cpu/hppa/atomicity.h: Same. * config/cpu/mips/atomicity.h: Same. * config/cpu/sparc/atomicity.h: Same. * config/cpu/i386/atomicity.h: Same. * config/cpu/i486/atomicity.h: Same. * config/cpu/sh/atomicity.h: Same. * config/cpu/generic/atomicity_mutex/atomicity.h: Same. * include/ext/pool_allocator.h: Same. * include/ext/bitmap_allocator.h: Same. * include/ext/rc_string_base.h: Same. * include/ext/mt_allocator.h: Same. * include/bits/locale_classes.h: Same. * include/bits/basic_string.h: Same. * include/bits/ios_base.h: Same. * include/tr1/memory: Same. * src/pool_allocator.cc: Same. * src/mt_allocator.cc: Same. * src/locale_init.cc: Same. * src/ios.cc: Same. * src/locale.cc: Same. * src/bitmap_allocator.cc: Same. * src/ios_init.cc: Same. * src/debug.cc: Same. From-SVN: r116942
2006-09-14 17:48:15 +08:00
#include <ext/atomicity.h>
#include <ext/concurrence.h>
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. Co-Authored-By: Jonathan Wakely <jwakely@redhat.com> From-SVN: r244051
2017-01-04 18:54:59 +08:00
#include <bits/atomic_lockfree_defines.h>
#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
&& (ATOMIC_INT_LOCK_FREE > 1) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
# include <climits>
# include <syscall.h>
# include <unistd.h>
# define _GLIBCXX_USE_FUTEX
# define _GLIBCXX_FUTEX_WAIT 0
# define _GLIBCXX_FUTEX_WAKE 1
#endif
2004-08-09 21:18:56 +08:00
// The IA64/generic ABI uses the first byte of the guard variable.
// The ARM EABI uses the least significant bit.
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
// Thread-safe static local initialization support.
#ifdef __GTHREADS
# ifndef _GLIBCXX_USE_FUTEX
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
namespace
{
atomicity.h: Move to... 2006-09-13 Benjamin Kosnik <bkoz@redhat.com> * include/bits/atomicity.h: Move to... * include/ext/atomicity.h: ...here. * include/bits/concurrence.h: Move to... * include/ext/concurrence.h: ...here. * include/Makefile.am (ext_headers): Additions. (bits_headers): Subtractions. * include/Makefile.in: Regenerate. * include/ext/bitmap_allocator.h (_Mutex), __threads_enabled, _Lock, _Auto_Lock): Subsume into... * include/bits/concurrence.h (__mutex): ..this. Error check locking and unlocking. (lock): Uglify to... (__scoped_lock): Use __mutex. (__glibcxx_mutex_define_initialized): Remove. (__glibcxx_mutex_type): Remove. * include/tr1/boost_shared_ptr.h: Formating tweaks, adjustments. (_Lock_policy): Move from here... * include/ext/concurrence.h: ... to here. (__shared_ptr_default_lock_mode): To __default_lock_policy. (_S_lockfree): To _S_atomic. Document. * libsupc++/guard.cc (static_mutex): Subsume into and fixup for... * include/ext/concurrence.h (__recursive_mutex): ...this. Error check locking and unlocking. * libsupc++/eh_alloc.cc: Use __scoped_lock. * config/os/aix/atomicity.h: Fixups for include paths, mutex to __scoped_mutex change, removal of locking defines. * config/os/irix/atomicity.h: Same. * config/cpu/cris/atomicity.h: Same. * config/cpu/m68k/atomicity.h: Same. * config/cpu/hppa/atomicity.h: Same. * config/cpu/mips/atomicity.h: Same. * config/cpu/sparc/atomicity.h: Same. * config/cpu/i386/atomicity.h: Same. * config/cpu/i486/atomicity.h: Same. * config/cpu/sh/atomicity.h: Same. * config/cpu/generic/atomicity_mutex/atomicity.h: Same. * include/ext/pool_allocator.h: Same. * include/ext/bitmap_allocator.h: Same. * include/ext/rc_string_base.h: Same. * include/ext/mt_allocator.h: Same. * include/bits/locale_classes.h: Same. * include/bits/basic_string.h: Same. * include/bits/ios_base.h: Same. * include/tr1/memory: Same. * src/pool_allocator.cc: Same. * src/mt_allocator.cc: Same. * src/locale_init.cc: Same. * src/ios.cc: Same. * src/locale.cc: Same. * src/bitmap_allocator.cc: Same. * src/ios_init.cc: Same. * src/debug.cc: Same. From-SVN: r116942
2006-09-14 17:48:15 +08:00
// A single mutex controlling all static initializations.
static __gnu_cxx::__recursive_mutex* static_mutex;
typedef char fake_recursive_mutex[sizeof(__gnu_cxx::__recursive_mutex)]
__attribute__ ((aligned(__alignof__(__gnu_cxx::__recursive_mutex))));
fake_recursive_mutex fake_mutex;
static void init()
{ static_mutex = new (&fake_mutex) __gnu_cxx::__recursive_mutex(); }
__gnu_cxx::__recursive_mutex&
get_static_mutex()
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once(&once, init);
return *static_mutex;
}
// Simple wrapper for exception safety.
struct mutex_wrapper
{
bool unlock;
mutex_wrapper() : unlock(true)
{ get_static_mutex().lock(); }
~mutex_wrapper()
{
if (unlock)
static_mutex->unlock();
}
};
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
}
# endif
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
# if defined(__GTHREAD_HAS_COND) && !defined(_GLIBCXX_USE_FUTEX)
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
namespace
{
// A single condition variable controlling all static initializations.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
static __gnu_cxx::__cond* static_cond;
// using a fake type to avoid initializing a static class.
typedef char fake_cond_t[sizeof(__gnu_cxx::__cond)]
__attribute__ ((aligned(__alignof__(__gnu_cxx::__cond))));
fake_cond_t fake_cond;
static void init_static_cond()
{ static_cond = new (&fake_cond) __gnu_cxx::__cond(); }
__gnu_cxx::__cond&
get_static_cond()
{
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
__gthread_once(&once, init_static_cond);
return *static_cond;
}
}
# endif
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
# ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
// Test the guard variable with a memory load with
// acquire semantics.
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
inline bool
__test_and_acquire (__cxxabiv1::__guard *g)
{
unsigned char __c;
unsigned char *__p = reinterpret_cast<unsigned char *>(g);
__atomic_load (__p, &__c, __ATOMIC_ACQUIRE);
(void) __p;
return _GLIBCXX_GUARD_TEST(&__c);
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
}
# define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
# endif
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
# ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
// Set the guard variable to 1 with memory order release semantics.
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
inline void
__set_and_release (__cxxabiv1::__guard *g)
{
unsigned char *__p = reinterpret_cast<unsigned char *>(g);
unsigned char val = 1;
__atomic_store (__p, &val, __ATOMIC_RELEASE);
(void) __p;
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
}
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
# endif
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
#else /* !__GTHREADS */
# undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
# undef _GLIBCXX_GUARD_SET_AND_RELEASE
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
#endif /* __GTHREADS */
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
//
// Here are C++ run-time routines for guarded initialization of static
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// variables. There are 4 scenarios under which these routines are called:
//
// 1. Threads not supported (__GTHREADS not defined)
// 2. Threads are supported but not enabled at run-time.
// 3. Threads enabled at run-time but __gthreads_* are not fully POSIX.
// 4. Threads enabled at run-time and __gthreads_* support all POSIX threads
// primitives we need here.
//
// The old code supported scenarios 1-3 but was broken since it used a global
// mutex for all threads and had the mutex locked during the whole duration of
// initialization of a guarded static variable. The following created a
// dead-lock with the old code.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
//
// Thread 1 acquires the global mutex.
// Thread 1 starts initializing static variable.
// Thread 1 creates thread 2 during initialization.
// Thread 2 attempts to acquire mutex to initialize another variable.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// Thread 2 blocks since thread 1 is locking the mutex.
// Thread 1 waits for result from thread 2 and also blocks. A deadlock.
//
// The new code here can handle this situation and thus is more robust. However,
// we need to use the POSIX thread condition variable, which is not supported
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// in all platforms, notably older versions of Microsoft Windows. The gthr*.h
// headers define a symbol __GTHREAD_HAS_COND for platforms that support POSIX
// like condition variables. For platforms that do not support condition
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// variables, we need to fall back to the old code.
// If _GLIBCXX_USE_FUTEX, no global mutex or condition variable is used,
// only atomic operations are used together with futex syscall.
// Valid values of the first integer in guard are:
// 0 No thread encountered the guarded init
// yet or it has been aborted.
// _GLIBCXX_GUARD_BIT The guarded static var has been successfully
// initialized.
// _GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
// and no other thread is waiting for its
// initialization.
// (_GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
// | _GLIBCXX_GUARD_WAITING_BIT) and some other threads are waiting until
// it is initialized.
namespace __cxxabiv1
{
#ifdef _GLIBCXX_USE_FUTEX
namespace
{
static inline int __guard_test_bit (const int __byte, const int __val)
{
union { int __i; char __c[sizeof (int)]; } __u = { 0 };
__u.__c[__byte] = __val;
return __u.__i;
}
}
#endif
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
static inline int
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
init_in_progress_flag(__guard* g)
{ return ((char *)g)[1]; }
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
static inline void
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
set_init_in_progress_flag(__guard* g, int v)
{ ((char *)g)[1] = v; }
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
static inline void
throw_recursive_init_exception()
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
{
#if __cpp_exceptions
atomicity.h: Move to... 2006-09-13 Benjamin Kosnik <bkoz@redhat.com> * include/bits/atomicity.h: Move to... * include/ext/atomicity.h: ...here. * include/bits/concurrence.h: Move to... * include/ext/concurrence.h: ...here. * include/Makefile.am (ext_headers): Additions. (bits_headers): Subtractions. * include/Makefile.in: Regenerate. * include/ext/bitmap_allocator.h (_Mutex), __threads_enabled, _Lock, _Auto_Lock): Subsume into... * include/bits/concurrence.h (__mutex): ..this. Error check locking and unlocking. (lock): Uglify to... (__scoped_lock): Use __mutex. (__glibcxx_mutex_define_initialized): Remove. (__glibcxx_mutex_type): Remove. * include/tr1/boost_shared_ptr.h: Formating tweaks, adjustments. (_Lock_policy): Move from here... * include/ext/concurrence.h: ... to here. (__shared_ptr_default_lock_mode): To __default_lock_policy. (_S_lockfree): To _S_atomic. Document. * libsupc++/guard.cc (static_mutex): Subsume into and fixup for... * include/ext/concurrence.h (__recursive_mutex): ...this. Error check locking and unlocking. * libsupc++/eh_alloc.cc: Use __scoped_lock. * config/os/aix/atomicity.h: Fixups for include paths, mutex to __scoped_mutex change, removal of locking defines. * config/os/irix/atomicity.h: Same. * config/cpu/cris/atomicity.h: Same. * config/cpu/m68k/atomicity.h: Same. * config/cpu/hppa/atomicity.h: Same. * config/cpu/mips/atomicity.h: Same. * config/cpu/sparc/atomicity.h: Same. * config/cpu/i386/atomicity.h: Same. * config/cpu/i486/atomicity.h: Same. * config/cpu/sh/atomicity.h: Same. * config/cpu/generic/atomicity_mutex/atomicity.h: Same. * include/ext/pool_allocator.h: Same. * include/ext/bitmap_allocator.h: Same. * include/ext/rc_string_base.h: Same. * include/ext/mt_allocator.h: Same. * include/bits/locale_classes.h: Same. * include/bits/basic_string.h: Same. * include/bits/ios_base.h: Same. * include/tr1/memory: Same. * src/pool_allocator.cc: Same. * src/mt_allocator.cc: Same. * src/locale_init.cc: Same. * src/ios.cc: Same. * src/locale.cc: Same. * src/bitmap_allocator.cc: Same. * src/ios_init.cc: Same. * src/debug.cc: Same. From-SVN: r116942
2006-09-14 17:48:15 +08:00
throw __gnu_cxx::recursive_init_error();
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#else
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
// Use __builtin_trap so we don't require abort().
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
__builtin_trap();
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#endif
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
}
// acquire() is a helper function used to acquire guard if thread support is
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// not compiled in or is compiled in but not enabled at run-time.
static int
acquire(__guard *g)
{
// Quit if the object is already initialized.
if (_GLIBCXX_GUARD_TEST(g))
return 0;
if (init_in_progress_flag(g))
throw_recursive_init_exception();
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
set_init_in_progress_flag(g, 1);
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
return 1;
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
}
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
extern "C"
int __cxa_guard_acquire (__guard *g)
{
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#ifdef __GTHREADS
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
// If the target can reorder loads, we need to insert a read memory
// barrier so that accesses to the guarded variable happen after the
// guard test.
if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
return 0;
# ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
// Use the same bits in the guard variable whether single-threaded or not,
// so that __cxa_guard_release and __cxa_guard_abort match the logic here
// even if __libc_single_threaded becomes false between now and then.
if (__gnu_cxx::__is_single_threaded())
{
// No need to use atomics, and no need to wait for other threads.
int *gi = (int *) (void *) g;
if (*gi == 0)
{
*gi = _GLIBCXX_GUARD_PENDING_BIT;
return 1;
}
else
throw_recursive_init_exception();
}
else
{
int *gi = (int *) (void *) g;
const int guard_bit = _GLIBCXX_GUARD_BIT;
const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
while (1)
{
int expected(0);
if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
// This thread should do the initialization.
return 1;
}
if (expected == guard_bit)
{
// Already initialized.
return 0;
}
if (expected == pending_bit)
{
// Use acquire here.
int newv = expected | waiting_bit;
if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
__ATOMIC_ACQ_REL,
__ATOMIC_ACQUIRE))
{
if (expected == guard_bit)
{
// Make a thread that failed to set the
// waiting bit exit the function earlier,
// if it detects that another thread has
// successfully finished initialising.
return 0;
}
if (expected == 0)
continue;
}
expected = newv;
}
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0);
}
}
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
# else // ! _GLIBCXX_USE_FUTEX
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
if (__gthread_active_p ())
{
mutex_wrapper mw;
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
while (1) // When this loop is executing, mutex is locked.
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
{
# ifdef __GTHREAD_HAS_COND
// The static is already initialized.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (_GLIBCXX_GUARD_TEST(g))
return 0; // The mutex will be unlocked via wrapper
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (init_in_progress_flag(g))
{
// The guarded static is currently being initialized by
// another thread, so we release mutex and wait for the
// condition variable. We will lock the mutex again after
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// this.
get_static_cond().wait_recursive(&get_static_mutex());
}
else
{
set_init_in_progress_flag(g, 1);
return 1; // The mutex will be unlocked via wrapper.
}
# else
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
// This provides compatibility with older systems not supporting
// POSIX like condition variables.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (acquire(g))
{
mw.unlock = false;
return 1; // The mutex still locked.
}
return 0; // The mutex will be unlocked via wrapper.
# endif
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
}
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
}
# endif
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
#endif // ! __GTHREADS
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
return acquire (g);
}
extern "C"
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
void __cxa_guard_abort (__guard *g) noexcept
{
#ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
if (__gnu_cxx::__is_single_threaded())
{
// No need to use atomics, and no other threads to wake.
int *gi = (int *) (void *) g;
*gi = 0;
return;
}
else
{
int *gi = (int *) (void *) g;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
int old = __atomic_exchange_n (gi, 0, __ATOMIC_ACQ_REL);
if ((old & waiting_bit) != 0)
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
return;
}
#elif defined(__GTHREAD_HAS_COND)
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (__gthread_active_p())
{
mutex_wrapper mw;
set_init_in_progress_flag(g, 0);
// If we abort, we still need to wake up all other threads waiting for
// the condition variable.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
get_static_cond().broadcast();
return;
}
#endif
set_init_in_progress_flag(g, 0);
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
// This provides compatibility with older systems not supporting POSIX like
// condition variables.
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
if (__gthread_active_p ())
static_mutex->unlock();
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#endif
}
extern "C"
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
void __cxa_guard_release (__guard *g) noexcept
{
#ifdef _GLIBCXX_USE_FUTEX
// If __atomic_* and futex syscall are supported, don't use any global
// mutex.
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
if (__gnu_cxx::__is_single_threaded())
{
int *gi = (int *) (void *) g;
*gi = _GLIBCXX_GUARD_BIT;
return;
}
else
{
int *gi = (int *) (void *) g;
const int guard_bit = _GLIBCXX_GUARD_BIT;
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
int old = __atomic_exchange_n (gi, guard_bit, __ATOMIC_ACQ_REL);
if ((old & waiting_bit) != 0)
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
return;
}
libstdc++: Use __libc_single_threaded to optimise atomics [PR 96817] 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.
2020-09-27 03:32:36 +08:00
#elif defined(__GTHREAD_HAS_COND)
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (__gthread_active_p())
{
mutex_wrapper mw;
set_init_in_progress_flag(g, 0);
_GLIBCXX_GUARD_SET_AND_RELEASE(g);
get_static_cond().broadcast();
return;
}
#endif
set_init_in_progress_flag(g, 0);
Add memory barriers to the double-checked locking used for static initialization. libstdc++: Add memory barriers to the double-checked locking used for static initialization. * libsupc++/guard.cc (__test_and_acquire): Define default. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE, __set_and_release) (_GLIBCXX_GUARD_SET_AND_RELEASE): Likewise. (recursion_push, recursion_pop): New abstraction functions. (__cxa_guard_acquire): Use _GLIBCXX_GUARD_TEST_AND_ACQUIRE. (__cxa_guard_release): Use _GLIBCXX_GUARD_SET_AND_RELEASE. * config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_TEST): Rename from _GLIBCXX_GUARD_ACQUIRE and reverse sense. (_GLIBCXX_GUARD_SET): Rename from _GLIBCXX_GUARD_RELEASE. * config/cpu/arm/cxxabi_tweaks.h: Likewise. * config/cpu/alpha/atomic_word.h (_GLIBCXX_READ_MEM_BARRIER) (_GLIBCXX_WRITE_MEM_BARRIER): Define. * config/cpu/powerpc/atomic_word.h: Likewise. * config/cpu/sparc/atomic_word.h: Likewise. * config/cpu/generic/atomic_word.h: Define them, commented out. * include/bits/atomicity.h: Define defaults. * config/cpu/ia64/atomic_word.h (__test_and_acquire) (__set_and_release): New inlines. (_GLIBCXX_GUARD_TEST_AND_ACQUIRE): Define. (_GLIBCXX_GUARD_SET_AND_RELEASE): Define. * libsupc++/guard.cc (acquire_1): Use __builtin_trap instead of abort(); gcc: * doc/tm.texi (TARGET_RELAXED_ORDERING): Document. * target.h (struct gcc_target): Add relaxed_ordering field. * target-def.h (TARGET_RELAXED_ORDERING): Define default. (TARGET_INITIALIZER): Add it. * config/alpha/alpha.c (TARGET_RELAXED_ORDERING): Define. * config/ia64/ia64.c (TARGET_RELAXED_ORDERING): Define. * config/rs6000/rs6000.c (TARGET_RELAXED_ORDERING): Define. * config/sparc/sparc.c (TARGET_RELAXED_ORDERING): Define. * cp/decl.c (expand_static_init): Don't use shortcut if targetm.relaxed_ordering. From-SVN: r92659
2004-12-28 12:36:54 +08:00
_GLIBCXX_GUARD_SET_AND_RELEASE (g);
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
#if defined(__GTHREADS) && !defined(__GTHREAD_HAS_COND)
// This provides compatibility with older systems not supporting POSIX like
// condition variables.
gthr-posix.h (__gthread_cond_broadcast, [...]): Add to extend interface for POSIX conditional variables. 2007-09-13 Doug Kwan <dougkwan@google.com> * gcc/gthr-posix.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-posix95.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. (__GTHREAD_HAS_COND): Macro defined to signify support of conditional variables. * gcc/gthr-single.h (__gthread_cond_broadcast, __gthread_cond_wait, __gthread_cond_wait_recursive): Add to extend interface for POSIX conditional variables. * gcc/gthr.h: Update comments to document new interface. * libstdc++-v3/include/ext/concurrent.h (class __mutex, class __recursive_mutex): Add new method gthread_mutex to access inner gthread mutex. [__GTHREAD_HAS_COND] (class __concurrence_broadcast_error, class __concurrence_wait_error, class __cond): Add. * guard.cc (recursive_push, recursive_pop): Delete. (init_in_progress_flag, set_init_in_progress_flag): Add to replace recursive_push and recursive_pop. (throw_recursive_init_exception): Add. (acquire, __cxa_guard_acquire, __cxa_guard_abort and __cxa_guard_release): [__GTHREAD_HAS_COND] Use a conditional for synchronization of static variable initialization. The global mutex is only held briefly when guards are accessed. [!__GTHREAD_HAS_COND] Fall back to the old code, which deadlocks. * testsuite/thread/guard.cc: Add new test. It deadlocks with the old locking code in libstdc++-v3/libsup++/guard.cc. From-SVN: r129030
2007-10-05 13:35:46 +08:00
if (__gthread_active_p())
static_mutex->unlock();
re PR c++/13684 (local static object variable constructed once but ctors and dtors called multiple times on same memory when called in multiple threads) PR c++/13684 * cp/decl.c (expand_static_init): Use thread-safety API. (register_dtor_fn): Return the call, don't expand it. * cp/tree.c (add_stmt_to_compound): New fn. (stabilize_call): Use it. * gimplify.c (gimplify_cleanup_point_expr): Handle CLEANUP_EH_ONLY. (gimple_push_cleanup): Add eh_only parm. (gimplify_target_expr): Pass it. * c.opt (-fno-threadsafe-statics): New option. * c-opts.c (c_common_handle_option): Handle it. * c-common.h (flag_threadsafe_statics): Declare it. * c-common.c (flag_threadsafe_statics): Record it. * doc/invoke.texi: Document it. * tsystem.h (_GNU_SOURCE): Define. * gthr-posix.h (__gthread_recursive_mutex_t): New typedef. (__GTHREAD_RECURSIVE_MUTEX_INIT): New macro. (__GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION): New macro. (__gthread_recursive_mutex_init_function): New fn. (__gthread_recursive_mutex_lock): New fn. (__gthread_recursive_mutex_trylock): New fn. (__gthread_recursive_mutex_unlock): New fn. * gthr-solaris.h, gthr-single.h, gthr-dce.h: Likewise. * gthr-win32.h, gthr-vxworks.h: Likewise. * gthr.h: Document. * libsupc++/guard.cc (static_mutex): Internal class implementing a recursive mutex which controls initialization of local statics. (__gnu_cxx::recursive_init): New exception class. (__cxa_guard_acquire): Deal with locking and recursion detection. (acquire_1, __cxa_guard_abort, __cxa_guard_release): Likewise. From-SVN: r86687
2004-08-28 10:33:54 +08:00
#endif
}
}