mirror of git://gcc.gnu.org/git/gcc.git
acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Check for pthread_rwlock_t.
2015-03-18 Jonathan Wakely <jwakely@redhat.com> Torvald Riegel <triegel@redhat.com> * acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Check for pthread_rwlock_t. * config.h.in: Regenerate. * configure: Regenerate. * include/std/shared_mutex: Check _GLIBCXX_USE_PTHREAD_RWLOCK_T. (shared_timed_mutex::_M_rwlock): Use PTHREAD_RWLOCK_INITIALIZER. (shared_timed_mutex::lock_shared()): Retry on EAGAIN. (shared_timed_mutex::try_lock_shared_until()): Retry on EAGAIN and EDEADLK. Co-Authored-By: Torvald Riegel <triegel@redhat.com> From-SVN: r221484
This commit is contained in:
parent
41cee85a34
commit
5e0216f173
|
|
@ -1,3 +1,15 @@
|
||||||
|
2015-03-18 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
Torvald Riegel <triegel@redhat.com>
|
||||||
|
|
||||||
|
* acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Check for pthread_rwlock_t.
|
||||||
|
* config.h.in: Regenerate.
|
||||||
|
* configure: Regenerate.
|
||||||
|
* include/std/shared_mutex: Check _GLIBCXX_USE_PTHREAD_RWLOCK_T.
|
||||||
|
(shared_timed_mutex::_M_rwlock): Use PTHREAD_RWLOCK_INITIALIZER.
|
||||||
|
(shared_timed_mutex::lock_shared()): Retry on EAGAIN.
|
||||||
|
(shared_timed_mutex::try_lock_shared_until()): Retry on EAGAIN and
|
||||||
|
EDEADLK.
|
||||||
|
|
||||||
2015-03-17 Jonathan Wakely <jwakely@redhat.com>
|
2015-03-17 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* libsupc++/nested_exception.h: Do not try to derive from final
|
* libsupc++/nested_exception.h: Do not try to derive from final
|
||||||
|
|
|
||||||
|
|
@ -3563,6 +3563,13 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
|
||||||
if test x"$ac_has_gthreads" = x"yes"; then
|
if test x"$ac_has_gthreads" = x"yes"; then
|
||||||
AC_DEFINE(_GLIBCXX_HAS_GTHREADS, 1,
|
AC_DEFINE(_GLIBCXX_HAS_GTHREADS, 1,
|
||||||
[Define if gthreads library is available.])
|
[Define if gthreads library is available.])
|
||||||
|
|
||||||
|
# Also check for pthread_rwlock_t for std::shared_timed_mutex in C++14
|
||||||
|
AC_CHECK_TYPE([pthread_rwlock_t],
|
||||||
|
[AC_DEFINE([_GLIBCXX_USE_PTHREAD_RWLOCK_T], 1,
|
||||||
|
[Define if POSIX read/write locks are available in <gthr.h>.])],
|
||||||
|
[],
|
||||||
|
[#include "gthr.h"])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||||
|
|
|
||||||
|
|
@ -851,6 +851,9 @@
|
||||||
/* Define if pthreads_num_processors_np is available in <pthread.h>. */
|
/* Define if pthreads_num_processors_np is available in <pthread.h>. */
|
||||||
#undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP
|
#undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP
|
||||||
|
|
||||||
|
/* Define if POSIX read/write locks are available in <gthr.h>. */
|
||||||
|
#undef _GLIBCXX_USE_PTHREAD_RWLOCK_T
|
||||||
|
|
||||||
/* Define if /dev/random and /dev/urandom are available for the random_device
|
/* Define if /dev/random and /dev/urandom are available for the random_device
|
||||||
of TR1 (Chapter 5.1). */
|
of TR1 (Chapter 5.1). */
|
||||||
#undef _GLIBCXX_USE_RANDOM_TR1
|
#undef _GLIBCXX_USE_RANDOM_TR1
|
||||||
|
|
|
||||||
|
|
@ -2498,6 +2498,60 @@ $as_echo "$ac_res" >&6; }
|
||||||
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||||
|
|
||||||
} # ac_fn_c_check_type
|
} # ac_fn_c_check_type
|
||||||
|
|
||||||
|
# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
|
||||||
|
# ---------------------------------------------
|
||||||
|
# Tests whether TYPE exists after having included INCLUDES, setting cache
|
||||||
|
# variable VAR accordingly.
|
||||||
|
ac_fn_cxx_check_type ()
|
||||||
|
{
|
||||||
|
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
|
||||||
|
$as_echo_n "checking for $2... " >&6; }
|
||||||
|
if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
eval "$3=no"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
$4
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
if (sizeof ($2))
|
||||||
|
return 0;
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
$4
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
if (sizeof (($2)))
|
||||||
|
return 0;
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||||
|
|
||||||
|
else
|
||||||
|
eval "$3=yes"
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
eval ac_res=\$$3
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
|
||||||
|
$as_echo "$ac_res" >&6; }
|
||||||
|
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
|
||||||
|
|
||||||
|
} # ac_fn_cxx_check_type
|
||||||
cat >config.log <<_ACEOF
|
cat >config.log <<_ACEOF
|
||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
@ -11539,7 +11593,7 @@ else
|
||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 11542 "configure"
|
#line 11596 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
|
|
@ -11645,7 +11699,7 @@ else
|
||||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||||
lt_status=$lt_dlunknown
|
lt_status=$lt_dlunknown
|
||||||
cat > conftest.$ac_ext <<_LT_EOF
|
cat > conftest.$ac_ext <<_LT_EOF
|
||||||
#line 11648 "configure"
|
#line 11702 "configure"
|
||||||
#include "confdefs.h"
|
#include "confdefs.h"
|
||||||
|
|
||||||
#if HAVE_DLFCN_H
|
#if HAVE_DLFCN_H
|
||||||
|
|
@ -15065,7 +15119,7 @@ fi
|
||||||
#
|
#
|
||||||
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
|
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15068 "configure"
|
#line 15122 "configure"
|
||||||
struct S { ~S(); };
|
struct S { ~S(); };
|
||||||
void bar();
|
void bar();
|
||||||
void foo()
|
void foo()
|
||||||
|
|
@ -15417,7 +15471,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
|
||||||
# Fake what AC_TRY_COMPILE does.
|
# Fake what AC_TRY_COMPILE does.
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15420 "configure"
|
#line 15474 "configure"
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef bool atomic_type;
|
typedef bool atomic_type;
|
||||||
|
|
@ -15452,7 +15506,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
|
||||||
rm -f conftest*
|
rm -f conftest*
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15455 "configure"
|
#line 15509 "configure"
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef short atomic_type;
|
typedef short atomic_type;
|
||||||
|
|
@ -15487,7 +15541,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
|
||||||
rm -f conftest*
|
rm -f conftest*
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15490 "configure"
|
#line 15544 "configure"
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
// NB: _Atomic_word not necessarily int.
|
// NB: _Atomic_word not necessarily int.
|
||||||
|
|
@ -15523,7 +15577,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
|
||||||
rm -f conftest*
|
rm -f conftest*
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15526 "configure"
|
#line 15580 "configure"
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
typedef long long atomic_type;
|
typedef long long atomic_type;
|
||||||
|
|
@ -15602,7 +15656,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
|
||||||
# unnecessary for this test.
|
# unnecessary for this test.
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15605 "configure"
|
#line 15659 "configure"
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
_Decimal32 d1;
|
_Decimal32 d1;
|
||||||
|
|
@ -15644,7 +15698,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||||
# unnecessary for this test.
|
# unnecessary for this test.
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15647 "configure"
|
#line 15701 "configure"
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct same
|
struct same
|
||||||
{ typedef T2 type; };
|
{ typedef T2 type; };
|
||||||
|
|
@ -15678,7 +15732,7 @@ $as_echo "$enable_int128" >&6; }
|
||||||
rm -f conftest*
|
rm -f conftest*
|
||||||
|
|
||||||
cat > conftest.$ac_ext << EOF
|
cat > conftest.$ac_ext << EOF
|
||||||
#line 15681 "configure"
|
#line 15735 "configure"
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct same
|
struct same
|
||||||
{ typedef T2 type; };
|
{ typedef T2 type; };
|
||||||
|
|
@ -78786,6 +78840,16 @@ $as_echo "$ac_has_gthreads" >&6; }
|
||||||
|
|
||||||
$as_echo "#define _GLIBCXX_HAS_GTHREADS 1" >>confdefs.h
|
$as_echo "#define _GLIBCXX_HAS_GTHREADS 1" >>confdefs.h
|
||||||
|
|
||||||
|
|
||||||
|
# Also check for pthread_rwlock_t for std::shared_timed_mutex in C++14
|
||||||
|
ac_fn_cxx_check_type "$LINENO" "pthread_rwlock_t" "ac_cv_type_pthread_rwlock_t" "#include \"gthr.h\"
|
||||||
|
"
|
||||||
|
if test "x$ac_cv_type_pthread_rwlock_t" = x""yes; then :
|
||||||
|
|
||||||
|
$as_echo "#define _GLIBCXX_USE_PTHREAD_RWLOCK_T 1" >>confdefs.h
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
CXXFLAGS="$ac_save_CXXFLAGS"
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
/// shared_timed_mutex
|
/// shared_timed_mutex
|
||||||
class shared_timed_mutex
|
class shared_timed_mutex
|
||||||
{
|
{
|
||||||
#if defined(__GTHREADS_CXX0X)
|
#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_T
|
||||||
typedef chrono::system_clock __clock_t;
|
typedef chrono::system_clock __clock_t;
|
||||||
|
|
||||||
|
#ifdef PTHREAD_RWLOCK_INITIALIZER
|
||||||
|
pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER;
|
||||||
|
|
||||||
|
public:
|
||||||
|
shared_timed_mutex() = default;
|
||||||
|
~shared_timed_mutex() = default;
|
||||||
|
#else
|
||||||
pthread_rwlock_t _M_rwlock;
|
pthread_rwlock_t _M_rwlock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -82,6 +89,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
// Errors not handled: EBUSY, EINVAL
|
// Errors not handled: EBUSY, EINVAL
|
||||||
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
shared_timed_mutex(const shared_timed_mutex&) = delete;
|
shared_timed_mutex(const shared_timed_mutex&) = delete;
|
||||||
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
|
shared_timed_mutex& operator=(const shared_timed_mutex&) = delete;
|
||||||
|
|
@ -165,12 +173,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
void
|
void
|
||||||
lock_shared()
|
lock_shared()
|
||||||
{
|
{
|
||||||
int __ret = pthread_rwlock_rdlock(&_M_rwlock);
|
int __ret;
|
||||||
|
// We retry if we exceeded the maximum number of read locks supported by
|
||||||
|
// the POSIX implementation; this can result in busy-waiting, but this
|
||||||
|
// is okay based on the current specification of forward progress
|
||||||
|
// guarantees by the standard.
|
||||||
|
do
|
||||||
|
__ret = pthread_rwlock_rdlock(&_M_rwlock);
|
||||||
|
while (__ret == EAGAIN);
|
||||||
if (__ret == EDEADLK)
|
if (__ret == EDEADLK)
|
||||||
__throw_system_error(int(errc::resource_deadlock_would_occur));
|
__throw_system_error(int(errc::resource_deadlock_would_occur));
|
||||||
if (__ret == EAGAIN)
|
|
||||||
// Maximum number of read locks has been exceeded.
|
|
||||||
__throw_system_error(int(errc::device_or_resource_busy));
|
|
||||||
// Errors not handled: EINVAL
|
// Errors not handled: EINVAL
|
||||||
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
||||||
}
|
}
|
||||||
|
|
@ -210,11 +222,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
static_cast<long>(__ns.count())
|
static_cast<long>(__ns.count())
|
||||||
};
|
};
|
||||||
|
|
||||||
int __ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts);
|
int __ret;
|
||||||
// If the maximum number of read locks has been exceeded, or we would
|
// Unlike for lock(), we are not allowed to throw an exception so if
|
||||||
// deadlock, we just fail to acquire the lock. Unlike for lock(),
|
// the maximum number of read locks has been exceeded, or we would
|
||||||
// we are not allowed to throw an exception.
|
// deadlock, we just try to acquire the lock again (and will time out
|
||||||
if (__ret == ETIMEDOUT || __ret == EAGAIN || __ret == EDEADLK)
|
// eventually).
|
||||||
|
// In cases where we would exceed the maximum number of read locks
|
||||||
|
// throughout the whole time until the timeout, we will fail to
|
||||||
|
// acquire the lock even if it would be logically free; however, this
|
||||||
|
// is allowed by the standard, and we made a "strong effort"
|
||||||
|
// (see C++14 30.4.1.4p26).
|
||||||
|
// For cases where the implementation detects a deadlock we
|
||||||
|
// intentionally block and timeout so that an early return isn't
|
||||||
|
// mistaken for a spurious failure, which might help users realise
|
||||||
|
// there is a deadlock.
|
||||||
|
do
|
||||||
|
__ret = pthread_rwlock_timedrdlock(&_M_rwlock, &__ts);
|
||||||
|
while (__ret == EAGAIN || __ret == EDEADLK);
|
||||||
|
if (__ret == ETIMEDOUT)
|
||||||
return false;
|
return false;
|
||||||
// Errors not handled: EINVAL
|
// Errors not handled: EINVAL
|
||||||
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
_GLIBCXX_DEBUG_ASSERT(__ret == 0);
|
||||||
|
|
@ -241,7 +266,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // defined(__GTHREADS_CXX0X)
|
#else // ! _GLIBCXX_USE_PTHREAD_RWLOCK_T
|
||||||
|
|
||||||
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
|
#if _GTHREAD_USE_MUTEX_TIMEDLOCK
|
||||||
struct _Mutex : mutex, __timed_mutex_impl<_Mutex>
|
struct _Mutex : mutex, __timed_mutex_impl<_Mutex>
|
||||||
|
|
@ -438,7 +463,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_M_gate1.notify_one();
|
_M_gate1.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !defined(__GTHREADS_CXX0X)
|
#endif // ! _GLIBCXX_USE_PTHREAD_RWLOCK_T
|
||||||
};
|
};
|
||||||
#endif // _GLIBCXX_HAS_GTHREADS
|
#endif // _GLIBCXX_HAS_GTHREADS
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue