2022-01-03 17:42:10 +08:00
|
|
|
// Copyright (C) 2002-2022 Free Software Foundation, Inc.
|
2002-11-26 07:17:31 +08:00
|
|
|
//
|
|
|
|
// 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
|
2009-04-09 23:00:19 +08:00
|
|
|
// the Free Software Foundation; either version 3, or (at your option)
|
2002-11-26 07:17:31 +08:00
|
|
|
// 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.
|
|
|
|
|
2009-04-09 23:00:19 +08:00
|
|
|
// 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.
|
2002-11-26 07:17:31 +08:00
|
|
|
|
2009-04-09 23:00:19 +08:00
|
|
|
// 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/>.
|
2002-11-26 07:17:31 +08:00
|
|
|
|
|
|
|
// Written by Mark Mitchell, CodeSourcery LLC, <mark@codesourcery.com>
|
2004-12-28 12:36:54 +08:00
|
|
|
// Thread support written by Jason Merrill, Red Hat Inc. <jason@redhat.com>
|
2002-11-26 07:17:31 +08:00
|
|
|
|
2005-11-22 08:19:07 +08:00
|
|
|
#include <bits/c++config.h>
|
2002-11-26 07:17:31 +08:00
|
|
|
#include <cxxabi.h>
|
2004-08-28 10:33:54 +08:00
|
|
|
#include <exception>
|
2006-10-12 04:18:36 +08:00
|
|
|
#include <new>
|
2006-09-14 17:48:15 +08:00
|
|
|
#include <ext/atomicity.h>
|
|
|
|
#include <ext/concurrence.h>
|
2017-01-04 18:54:59 +08:00
|
|
|
#include <bits/atomic_lockfree_defines.h>
|
2008-01-09 00:14:49 +08:00
|
|
|
#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
|
2011-12-01 10:20:32 +08:00
|
|
|
&& (ATOMIC_INT_LOCK_FREE > 1) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
|
2008-01-09 00:14:49 +08:00
|
|
|
# include <climits>
|
|
|
|
# include <syscall.h>
|
2011-07-16 05:52:06 +08:00
|
|
|
# include <unistd.h>
|
2008-01-09 00:14:49 +08:00
|
|
|
# define _GLIBCXX_USE_FUTEX
|
|
|
|
# define _GLIBCXX_FUTEX_WAIT 0
|
|
|
|
# define _GLIBCXX_FUTEX_WAKE 1
|
|
|
|
#endif
|
2002-11-26 07:17:31 +08:00
|
|
|
|
2004-08-09 21:18:56 +08:00
|
|
|
// The IA64/generic ABI uses the first byte of the guard variable.
|
2004-06-26 01:15:46 +08:00
|
|
|
// The ARM EABI uses the least significant bit.
|
|
|
|
|
2004-08-28 10:33:54 +08:00
|
|
|
// Thread-safe static local initialization support.
|
|
|
|
#ifdef __GTHREADS
|
2008-01-09 00:14:49 +08:00
|
|
|
# ifndef _GLIBCXX_USE_FUTEX
|
2004-08-28 10:33:54 +08:00
|
|
|
namespace
|
|
|
|
{
|
2006-09-14 17:48:15 +08:00
|
|
|
// A single mutex controlling all static initializations.
|
2006-10-12 04:18:36 +08:00
|
|
|
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;
|
|
|
|
}
|
2007-10-11 07:06:08 +08:00
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
};
|
2004-08-28 10:33:54 +08:00
|
|
|
}
|
2008-01-09 00:14:49 +08:00
|
|
|
# endif
|
2004-12-28 12:36:54 +08:00
|
|
|
|
2008-01-09 00:14:49 +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
|
|
|
|
{
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
2008-01-09 00:14:49 +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
|
|
|
|
2008-01-09 00:14:49 +08:00
|
|
|
# ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
|
2015-06-12 17:49:41 +08:00
|
|
|
|
|
|
|
// Test the guard variable with a memory load with
|
|
|
|
// acquire semantics.
|
|
|
|
|
2004-12-28 12:36:54 +08:00
|
|
|
inline bool
|
|
|
|
__test_and_acquire (__cxxabiv1::__guard *g)
|
|
|
|
{
|
2015-06-12 17:49:41 +08:00
|
|
|
unsigned char __c;
|
|
|
|
unsigned char *__p = reinterpret_cast<unsigned char *>(g);
|
|
|
|
__atomic_load (__p, &__c, __ATOMIC_ACQUIRE);
|
2016-03-18 23:44:44 +08:00
|
|
|
(void) __p;
|
2015-06-12 17:49:41 +08:00
|
|
|
return _GLIBCXX_GUARD_TEST(&__c);
|
2004-12-28 12:36:54 +08:00
|
|
|
}
|
2008-01-09 00:14:49 +08:00
|
|
|
# define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
|
|
|
|
# endif
|
2004-08-28 10:33:54 +08:00
|
|
|
|
2008-01-09 00:14:49 +08:00
|
|
|
# ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
|
2015-06-12 17:49:41 +08:00
|
|
|
|
|
|
|
// Set the guard variable to 1 with memory order release semantics.
|
|
|
|
|
2004-12-28 12:36:54 +08:00
|
|
|
inline void
|
|
|
|
__set_and_release (__cxxabiv1::__guard *g)
|
|
|
|
{
|
2015-06-12 17:49:41 +08:00
|
|
|
unsigned char *__p = reinterpret_cast<unsigned char *>(g);
|
|
|
|
unsigned char val = 1;
|
|
|
|
__atomic_store (__p, &val, __ATOMIC_RELEASE);
|
2016-03-18 23:44:44 +08:00
|
|
|
(void) __p;
|
2004-12-28 12:36:54 +08:00
|
|
|
}
|
2008-01-09 00:14:49 +08:00
|
|
|
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
|
|
|
|
# endif
|
2004-12-28 12:36:54 +08:00
|
|
|
|
|
|
|
#else /* !__GTHREADS */
|
|
|
|
|
2008-01-09 00:14:49 +08:00
|
|
|
# undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
|
|
|
|
# undef _GLIBCXX_GUARD_SET_AND_RELEASE
|
|
|
|
# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
|
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
|
|
|
//
|
2011-05-26 07:43:32 +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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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.
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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.
|
|
|
|
//
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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.
|
2008-01-09 00:14:49 +08:00
|
|
|
|
2011-05-26 07:43:32 +08:00
|
|
|
// If _GLIBCXX_USE_FUTEX, no global mutex or condition variable is used,
|
2008-01-09 00:14:49 +08:00
|
|
|
// 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.
|
|
|
|
|
2002-11-26 07:17:31 +08:00
|
|
|
namespace __cxxabiv1
|
|
|
|
{
|
2008-01-09 00:14:49 +08:00
|
|
|
#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
|
|
|
|
|
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]; }
|
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; }
|
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()
|
2004-08-28 10:33:54 +08:00
|
|
|
{
|
2014-12-12 23:58:49 +08:00
|
|
|
#if __cpp_exceptions
|
2006-09-14 17:48:15 +08:00
|
|
|
throw __gnu_cxx::recursive_init_error();
|
2004-08-28 10:33:54 +08:00
|
|
|
#else
|
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();
|
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
|
|
|
}
|
|
|
|
|
2011-05-26 07:43:32 +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))
|
2008-01-09 00:14:49 +08:00
|
|
|
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);
|
2004-12-28 12:36:54 +08:00
|
|
|
return 1;
|
2004-08-28 10:33:54 +08:00
|
|
|
}
|
2004-12-28 12:36:54 +08:00
|
|
|
|
2002-11-26 07:17:31 +08:00
|
|
|
extern "C"
|
|
|
|
int __cxa_guard_acquire (__guard *g)
|
|
|
|
{
|
2004-08-28 10:33:54 +08:00
|
|
|
#ifdef __GTHREADS
|
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;
|
|
|
|
|
2008-01-09 00:14:49 +08:00
|
|
|
# ifdef _GLIBCXX_USE_FUTEX
|
2012-02-11 02:20:43 +08:00
|
|
|
// If __atomic_* and futex syscall are supported, don't use any global
|
2008-01-09 00:14:49 +08:00
|
|
|
// 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
|
2008-01-09 00:14:49 +08:00
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2012-09-07 04:31:08 +08:00
|
|
|
int expected(0);
|
2012-02-14 05:30:31 +08:00
|
|
|
if (__atomic_compare_exchange_n(gi, &expected, pending_bit, false,
|
|
|
|
__ATOMIC_ACQ_REL,
|
2012-09-11 23:22:54 +08:00
|
|
|
__ATOMIC_ACQUIRE))
|
2008-01-09 00:14:49 +08:00
|
|
|
{
|
2012-02-11 02:20:43 +08:00
|
|
|
// This thread should do the initialization.
|
|
|
|
return 1;
|
2008-01-09 00:14:49 +08:00
|
|
|
}
|
2012-02-11 02:20:43 +08:00
|
|
|
|
|
|
|
if (expected == guard_bit)
|
|
|
|
{
|
|
|
|
// Already initialized.
|
|
|
|
return 0;
|
|
|
|
}
|
2012-09-07 04:31:08 +08:00
|
|
|
|
2012-02-11 02:20:43 +08:00
|
|
|
if (expected == pending_bit)
|
|
|
|
{
|
2012-09-07 04:31:08 +08:00
|
|
|
// Use acquire here.
|
2012-02-11 02:20:43 +08:00
|
|
|
int newv = expected | waiting_bit;
|
2012-02-14 05:30:31 +08:00
|
|
|
if (!__atomic_compare_exchange_n(gi, &expected, newv, false,
|
2012-02-11 02:20:43 +08:00
|
|
|
__ATOMIC_ACQ_REL,
|
2012-09-07 04:31:08 +08:00
|
|
|
__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;
|
|
|
|
}
|
2012-02-11 02:20:43 +08:00
|
|
|
|
|
|
|
expected = newv;
|
|
|
|
}
|
|
|
|
|
|
|
|
syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, expected, 0);
|
2008-01-09 00:14:49 +08:00
|
|
|
}
|
|
|
|
}
|
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
|
2004-08-28 10:33:54 +08:00
|
|
|
if (__gthread_active_p ())
|
|
|
|
{
|
2006-10-12 04:18:36 +08:00
|
|
|
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.
|
2004-08-28 10:33:54 +08:00
|
|
|
{
|
2008-01-09 00:14:49 +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
|
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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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.
|
|
|
|
}
|
2008-01-09 00:14:49 +08:00
|
|
|
# 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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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.
|
2008-01-09 00:14:49 +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
|
|
|
}
|
2004-08-28 10:33:54 +08:00
|
|
|
}
|
2008-01-09 00:14:49 +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
|
2004-08-28 10:33:54 +08:00
|
|
|
|
2006-10-12 04:18:36 +08:00
|
|
|
return acquire (g);
|
2002-11-26 07:17:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2002-11-26 07:17:31 +08:00
|
|
|
{
|
2008-01-09 00:14:49 +08:00
|
|
|
#ifdef _GLIBCXX_USE_FUTEX
|
2012-02-11 02:20:43 +08:00
|
|
|
// If __atomic_* and futex syscall are supported, don't use any global
|
2008-01-09 00:14:49 +08:00
|
|
|
// 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
|
2008-01-09 00:14:49 +08:00
|
|
|
{
|
|
|
|
int *gi = (int *) (void *) g;
|
|
|
|
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
|
2012-02-11 02:20:43 +08:00
|
|
|
int old = __atomic_exchange_n (gi, 0, __ATOMIC_ACQ_REL);
|
2008-01-09 00:14:49 +08:00
|
|
|
|
|
|
|
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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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
|
2011-05-26 07:43:32 +08:00
|
|
|
// condition variables.
|
2004-08-28 10:33:54 +08:00
|
|
|
if (__gthread_active_p ())
|
2006-10-12 04:18:36 +08:00
|
|
|
static_mutex->unlock();
|
2004-08-28 10:33:54 +08:00
|
|
|
#endif
|
2002-11-26 07:17:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2002-11-26 07:17:31 +08:00
|
|
|
{
|
2008-01-09 00:14:49 +08:00
|
|
|
#ifdef _GLIBCXX_USE_FUTEX
|
2012-02-11 02:20:43 +08:00
|
|
|
// If __atomic_* and futex syscall are supported, don't use any global
|
2008-01-09 00:14:49 +08:00
|
|
|
// 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
|
2008-01-09 00:14:49 +08:00
|
|
|
{
|
|
|
|
int *gi = (int *) (void *) g;
|
|
|
|
const int guard_bit = _GLIBCXX_GUARD_BIT;
|
|
|
|
const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
|
2012-02-11 02:20:43 +08:00
|
|
|
int old = __atomic_exchange_n (gi, guard_bit, __ATOMIC_ACQ_REL);
|
2008-01-09 00:14:49 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
2008-01-09 00:14:49 +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);
|
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
|
2011-05-26 07:43:32 +08:00
|
|
|
// 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())
|
2006-10-12 04:18:36 +08:00
|
|
|
static_mutex->unlock();
|
2004-08-28 10:33:54 +08:00
|
|
|
#endif
|
2002-11-26 07:17:31 +08:00
|
|
|
}
|
|
|
|
}
|