This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] Optimized __cxa_guard_{acquire,release,abort} for Linux
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Paolo Carlini <pcarlini at suse dot de>
- Cc: Richard Guenther <richard dot guenther at gmail dot com>, Benjamin Kosnik <bkoz at redhat dot com>, Jason Merrill <jason at redhat dot com>, gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Wed, 2 Jan 2008 05:29:16 -0500
- Subject: [PATCH] Optimized __cxa_guard_{acquire,release,abort} for Linux
- References: <20071231133948.GQ20451@devserv.devel.redhat.com> <84fc9c000712310800pb646954y47cd3c52fcf0dd4f@mail.gmail.com> <47791391.9050901@suse.de>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
On Mon, Dec 31, 2007 at 05:06:41PM +0100, Paolo Carlini wrote:
> Richard Guenther wrote:
> > This would also "fix" PR33960, right? So at least for me it would be
Yes.
> > worthwhile to
> > do for 4.3 ;)
> >
> Thanks Richard for your feedback. My first impression (while I cannot
> say I understand all the technical details of the approach) is also very
> good. I would suggest working on the configury bits, while waiting for
> more feedback.
Here is the patch together with the configure bits. For native build
when neither --{enable,disable}-linux-futex is given the same rules as
in libgomp configury are used, --enable-linux-futex enables it
unconditionally (and errors if SYS_futex isn't defined in headers),
--disable-linux-futex disables it. For cross only explicit
--enable-linux-futex will enable it, as we shouldn't do link tests.
2008-01-02 Jakub Jelinek <jakub@redhat.com>
* configure.ac (--enable-linux-futex): Add new configure option.
(HAVE_LINUX_FUTEX): New AC_DEFINE.
* configure: Rebuilt.
* config.h.in: Rebuilt.
* config/cpu/generic/cxxabi_tweaks.h (_GLIBCXX_GUARD_BIT,
_GLIBCXX_GUARD_PENDING_BIT, _GLIBCXX_GUARD_WAITING_BIT): Define.
* config/cpu/arm/cxxabi_tweaks.h (_GLIBCXX_GUARD_BIT,
_GLIBCXX_GUARD_PENDING_BIT, _GLIBCXX_GUARD_WAITING_BIT): Define.
* libsupc++/guard.cc: Include climits and syscall.h.
(_GLIBCXX_USE_FUTEX): Define if futex syscall and atomic builtins
are supported.
(_GLIBCXX_FUTEX_WAIT, _GLIBCXX_FUTEX_WAKE): Likewise.
(__guard_test_bit): New static inline.
(__cxa_guard_acquire, __cxa_guard_release, __cxa_guard_abort): Use
atomic builtins and futex syscall if _GLIBCXX_USE_FUTEX.
--- libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h.jj 2007-12-31 20:55:23.000000000 +0100
+++ libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h 2008-01-02 10:23:32.000000000 +0100
@@ -1,6 +1,6 @@
// Control various target specific ABI tweaks. ARM version.
-// Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -46,6 +46,9 @@ namespace __cxxabiv1
// guard variable. */
#define _GLIBCXX_GUARD_TEST(x) ((*(x) & 1) != 0)
#define _GLIBCXX_GUARD_SET(x) *(x) = 1
+#define _GLIBCXX_GUARD_BIT 1
+#define _GLIBCXX_GUARD_PENDING_BIT __guard_test_bit (1, 1)
+#define _GLIBCXX_GUARD_WAITING_BIT __guard_test_bit (1, 2)
typedef int __guard;
// We also want the element size in array cookies.
@@ -62,6 +65,9 @@ namespace __cxxabiv1
// The generic ABI uses the first byte of a 64-bit guard variable.
#define _GLIBCXX_GUARD_TEST(x) (*(char *) (x) != 0)
#define _GLIBCXX_GUARD_SET(x) *(char *) (x) = 1
+#define _GLIBCXX_GUARD_BIT __guard_test_bit (0, 1)
+#define _GLIBCXX_GUARD_PENDING_BIT __guard_test_bit (1, 1)
+#define _GLIBCXX_GUARD_WAITING_BIT __guard_test_bit (1, 2)
__extension__ typedef int __guard __attribute__((mode (__DI__)));
// __cxa_vec_ctor has void return type.
--- libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h.jj 2007-12-31 20:55:23.000000000 +0100
+++ libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h 2008-01-02 10:23:32.000000000 +0100
@@ -1,6 +1,6 @@
// Control various target specific ABI tweaks. Generic version.
-// Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -44,6 +44,9 @@ namespace __cxxabiv1
// The generic ABI uses the first byte of a 64-bit guard variable.
#define _GLIBCXX_GUARD_TEST(x) (*(char *) (x) != 0)
#define _GLIBCXX_GUARD_SET(x) *(char *) (x) = 1
+#define _GLIBCXX_GUARD_BIT __guard_test_bit (0, 1)
+#define _GLIBCXX_GUARD_PENDING_BIT __guard_test_bit (1, 1)
+#define _GLIBCXX_GUARD_WAITING_BIT __guard_test_bit (1, 2)
__extension__ typedef int __guard __attribute__((mode (__DI__)));
// __cxa_vec_ctor has void return type.
--- libstdc++-v3/libsupc++/guard.cc.jj 2007-12-31 20:55:22.000000000 +0100
+++ libstdc++-v3/libsupc++/guard.cc 2008-01-02 11:15:04.000000000 +0100
@@ -35,12 +35,21 @@
#include <new>
#include <ext/atomicity.h>
#include <ext/concurrence.h>
+#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
+ && defined(_GLIBCXX_ATOMIC_BUILTINS) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
+# include <climits>
+# include <syscall.h>
+# define _GLIBCXX_USE_FUTEX
+# define _GLIBCXX_FUTEX_WAIT 0
+# define _GLIBCXX_FUTEX_WAKE 1
+#endif
// The IA64/generic ABI uses the first byte of the guard variable.
// The ARM EABI uses the least significant bit.
// Thread-safe static local initialization support.
#ifdef __GTHREADS
+# ifndef _GLIBCXX_USE_FUTEX
namespace
{
// A single mutex controlling all static initializations.
@@ -75,8 +84,9 @@ namespace
}
};
}
+# endif
-#ifdef __GTHREAD_HAS_COND
+# if defined(__GTHREAD_HAS_COND) && !defined(_GLIBCXX_USE_FUTEX)
namespace
{
// A single conditional variable controlling all static initializations.
@@ -98,9 +108,9 @@ namespace
return *static_cond;
}
}
-#endif
+# endif
-#ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
+# ifndef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
inline bool
__test_and_acquire (__cxxabiv1::__guard *g)
{
@@ -108,24 +118,24 @@ __test_and_acquire (__cxxabiv1::__guard
_GLIBCXX_READ_MEM_BARRIER;
return b;
}
-#define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
-#endif
+# define _GLIBCXX_GUARD_TEST_AND_ACQUIRE(G) __test_and_acquire (G)
+# endif
-#ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
+# ifndef _GLIBCXX_GUARD_SET_AND_RELEASE
inline void
__set_and_release (__cxxabiv1::__guard *g)
{
_GLIBCXX_WRITE_MEM_BARRIER;
_GLIBCXX_GUARD_SET (g);
}
-#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
-#endif
+# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) __set_and_release (G)
+# endif
#else /* !__GTHREADS */
-#undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
-#undef _GLIBCXX_GUARD_SET_AND_RELEASE
-#define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
+# undef _GLIBCXX_GUARD_TEST_AND_ACQUIRE
+# undef _GLIBCXX_GUARD_SET_AND_RELEASE
+# define _GLIBCXX_GUARD_SET_AND_RELEASE(G) _GLIBCXX_GUARD_SET (G)
#endif /* __GTHREADS */
@@ -176,8 +186,35 @@ namespace __gnu_cxx
// headers define a symbol __GTHREAD_HAS_COND for platforms that support POSIX
// like conditional variables. For platforms that do not support conditional
// variables, we need to fall back to the old code.
+
+// If _GLIBCXX_USE_FUTEX, no global mutex or conditional variable is used,
+// only atomic operations are used together with futex syscall.
+// Valid values of the first integer in guard are:
+// 0 No thread encountered the guarded init
+// yet or it has been aborted.
+// _GLIBCXX_GUARD_BIT The guarded static var has been successfully
+// initialized.
+// _GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
+// and no other thread is waiting for its
+// initialization.
+// (_GLIBCXX_GUARD_PENDING_BIT The guarded static var is being initialized
+// | _GLIBCXX_GUARD_WAITING_BIT) and some other threads are waiting until
+// it is initialized.
+
namespace __cxxabiv1
{
+#ifdef _GLIBCXX_USE_FUTEX
+ namespace
+ {
+ static inline int __guard_test_bit (const int __byte, const int __val)
+ {
+ union { int __i; char __c[sizeof (int)]; } __u = { 0 };
+ __u.__c[__byte] = __val;
+ return __u.__i;
+ }
+ }
+#endif
+
static inline int
init_in_progress_flag(__guard* g)
{ return ((char *)g)[1]; }
@@ -207,7 +244,7 @@ namespace __cxxabiv1
return 0;
if (init_in_progress_flag(g))
- throw_recursive_init_exception();
+ throw_recursive_init_exception();
set_init_in_progress_flag(g, 1);
return 1;
@@ -223,14 +260,46 @@ namespace __cxxabiv1
if (_GLIBCXX_GUARD_TEST_AND_ACQUIRE (g))
return 0;
+# ifdef _GLIBCXX_USE_FUTEX
+ // If __sync_* and futex syscall are supported, don't use any global
+ // mutex.
+ if (__gthread_active_p ())
+ {
+ int *gi = (int *) (void *) g;
+ const int guard_bit = _GLIBCXX_GUARD_BIT;
+ const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
+ const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
+
+ while (1)
+ {
+ int old = __sync_val_compare_and_swap (gi, 0, pending_bit);
+ if (old == 0)
+ return 1; // This thread should do the initialization.
+
+ if (old == guard_bit)
+ return 0; // Already initialized.
+
+ if (old == pending_bit)
+ {
+ int newv = old | waiting_bit;
+ if (__sync_val_compare_and_swap (gi, old, newv) != old)
+ continue;
+
+ old = newv;
+ }
+
+ syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAIT, old, 0);
+ }
+ }
+# else
if (__gthread_active_p ())
{
mutex_wrapper mw;
while (1) // When this loop is executing, mutex is locked.
{
-#ifdef __GTHREAD_HAS_COND
- // The static is allready initialized.
+# ifdef __GTHREAD_HAS_COND
+ // The static is already initialized.
if (_GLIBCXX_GUARD_TEST(g))
return 0; // The mutex will be unlocked via wrapper
@@ -247,7 +316,7 @@ namespace __cxxabiv1
set_init_in_progress_flag(g, 1);
return 1; // The mutex will be unlocked via wrapper.
}
-#else
+# else
// This provides compatibility with older systems not supporting
// POSIX like conditional variables.
if (acquire(g))
@@ -256,9 +325,10 @@ namespace __cxxabiv1
return 1; // The mutex still locked.
}
return 0; // The mutex will be unlocked via wrapper.
-#endif
+# endif
}
}
+# endif
#endif
return acquire (g);
@@ -267,7 +337,35 @@ namespace __cxxabiv1
extern "C"
void __cxa_guard_abort (__guard *g)
{
-#ifdef __GTHREAD_HAS_COND
+#ifdef _GLIBCXX_USE_FUTEX
+ // If __sync_* and futex syscall are supported, don't use any global
+ // mutex.
+ if (__gthread_active_p ())
+ {
+ int *gi = (int *) (void *) g;
+ const int pending_bit = _GLIBCXX_GUARD_PENDING_BIT;
+ const int waiting_bit = _GLIBCXX_GUARD_WAITING_BIT;
+ int old;
+
+ old = __sync_val_compare_and_swap (gi, pending_bit, 0);
+ if (old == (pending_bit | waiting_bit))
+ {
+ while (1)
+ {
+ int newv = old & ~(pending_bit | waiting_bit);
+ int oldv = __sync_val_compare_and_swap (gi, old, newv);
+
+ if (oldv == old)
+ break;
+ if ((oldv & pending_bit) == 0)
+ break;
+ old = oldv;
+ }
+ syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
+ }
+ return;
+ }
+#elif defined(__GTHREAD_HAS_COND)
if (__gthread_active_p())
{
mutex_wrapper mw;
@@ -293,7 +391,33 @@ namespace __cxxabiv1
extern "C"
void __cxa_guard_release (__guard *g)
{
-#ifdef __GTHREAD_HAS_COND
+#ifdef _GLIBCXX_USE_FUTEX
+ // If __sync_* and futex syscall are supported, don't use any global
+ // mutex.
+ if (__gthread_active_p ())
+ {
+ 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;
+ int old;
+
+ old = __sync_val_compare_and_swap (gi, pending_bit, guard_bit);
+ if (old == (pending_bit | waiting_bit))
+ {
+ while (1)
+ {
+ int oldv = __sync_val_compare_and_swap (gi, old, guard_bit);
+
+ if (oldv == old || oldv == guard_bit)
+ break;
+ old = oldv;
+ }
+ syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX);
+ }
+ return;
+ }
+#elif defined(__GTHREAD_HAS_COND)
if (__gthread_active_p())
{
mutex_wrapper mw;
--- libstdc++-v3/configure.ac.jj 2007-09-14 11:54:41.000000000 +0200
+++ libstdc++-v3/configure.ac 2008-01-02 11:04:42.000000000 +0100
@@ -128,6 +128,9 @@ if test $atomicity_dir = cpu/generic/ato
fi
fi
+GLIBCXX_ENABLE(linux-futex,default, ,[use the Linux futex system call],
+ permit yes|no|default)
+
GLIBCXX_CHECK_COMPILER_FEATURES
if $GLIBCXX_IS_NATIVE; then
@@ -188,6 +191,55 @@ if $GLIBCXX_IS_NATIVE; then
# For iconv support.
AM_ICONV
+ case "$target" in
+ *-linux*)
+ case "$enable_linux_futex" in
+ default)
+ # If headers don't have gettid/futex syscalls definition, then
+ # default to no, otherwise there will be compile time failures.
+ # Otherwise, default to yes. If we don't detect we are
+ # compiled/linked against NPTL and not cross-compiling, check
+ # if programs are run by default against NPTL and if not, issue
+ # a warning.
+ enable_linux_futex=no
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <sys/syscall.h>
+ int lk;],
+ [syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);])],
+ [save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+ #include <pthread.h>
+ pthread_t th; void *status;],
+ [pthread_tryjoin_np (th, &status);])],[enable_linux_futex=yes],
+ [if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null \
+ | LC_ALL=C grep -i NPTL > /dev/null 2>/dev/null; then :; else
+ AC_MSG_WARN([The kernel might not support futex or gettid syscalls.
+If so, please configure with --disable-linux-futex])
+ fi
+ enable_linux_futex=yes])
+ LIBS="$save_LIBS"])
+ ;;
+ yes)
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <sys/syscall.h>
+ int lk;],
+ [syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);])],[],
+ [AC_MSG_ERROR([SYS_gettid and SYS_futex required for --enable-linux-futex])])
+ ;;
+ esac
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+
else
# This lets us hard-code the functionality we know we'll have in the cross
@@ -296,6 +348,31 @@ else
# Assume we have _Unwind_GetIPInfo for cross-compiles.
AC_DEFINE(HAVE_GETIPINFO)
+ case "$target" in
+ *-linux*)
+ case "$enable_linux_futex" in
+ yes)
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <sys/syscall.h>
+ int lk;],
+ [syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);])],[],
+ [AC_MSG_ERROR([SYS_gettid and SYS_futex required for --enable-linux-futex])])
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+
+fi
+
+if test x$enable_linux_futex = xyes; then
+ AC_DEFINE(HAVE_LINUX_FUTEX, 1, [Define if futex syscall is available.])
fi
# This depends on GLIBCXX CHECK_LINKER_FEATURES, but without it assumes no.
--- libstdc++-v3/configure.jj 2007-11-10 01:15:03.000000000 +0100
+++ libstdc++-v3/configure 2008-01-02 11:04:54.000000000 +0100
@@ -1051,6 +1051,8 @@ Optional Features:
--enable-fully-dynamic-string
do not put empty strings in per-process static
memory [default=no]
+ --enable-linux-futex use the Linux futex system call
+ [default=default]
--enable-tls Use thread-local storage [default=yes]
--disable-rpath do not hardcode runtime library paths
--enable-symvers=STYLE enables symbol versioning of the shared library
@@ -17848,6 +17850,22 @@ echo "$as_me: WARNING: Performance of ce
fi
fi
+ # Check whether --enable-linux-futex or --disable-linux-futex was given.
+if test "${enable_linux_futex+set}" = set; then
+ enableval="$enable_linux_futex"
+
+ case "$enableval" in
+ yes|no|default) ;;
+ *) { { echo "$as_me:$LINENO: error: Unknown argument to enable/disable linux-futex" >&5
+echo "$as_me: error: Unknown argument to enable/disable linux-futex" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+else
+ enable_linux_futex=default
+fi;
+
+
# All these tests are for C++; save the language and the compiler flags.
# The CXXFLAGS thing is suspicious, but based on similar bits previously
@@ -42519,6 +42537,196 @@ _ACEOF
fi
+ case "$target" in
+ *-linux*)
+ case "$enable_linux_futex" in
+ default)
+ # If headers don't have gettid/futex syscalls definition, then
+ # default to no, otherwise there will be compile time failures.
+ # Otherwise, default to yes. If we don't detect we are
+ # compiled/linked against NPTL and not cross-compiling, check
+ # if programs are run by default against NPTL and if not, issue
+ # a warning.
+ enable_linux_futex=no
+ if test x$gcc_no_link = xyes; then
+ { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
+echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/syscall.h>
+ int lk;
+int
+main ()
+{
+syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ save_LIBS="$LIBS"
+ LIBS="-lpthread $LIBS"
+ if test x$gcc_no_link = xyes; then
+ { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
+echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifndef _GNU_SOURCE
+ #define _GNU_SOURCE 1
+ #endif
+ #include <pthread.h>
+ pthread_t th; void *status;
+int
+main ()
+{
+pthread_tryjoin_np (th, &status);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ enable_linux_futex=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null \
+ | LC_ALL=C grep -i NPTL > /dev/null 2>/dev/null; then :; else
+ { echo "$as_me:$LINENO: WARNING: The kernel might not support futex or gettid syscalls.
+If so, please configure with --disable-linux-futex" >&5
+echo "$as_me: WARNING: The kernel might not support futex or gettid syscalls.
+If so, please configure with --disable-linux-futex" >&2;}
+ fi
+ enable_linux_futex=yes
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS="$save_LIBS"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+ yes)
+ if test x$gcc_no_link = xyes; then
+ { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5
+echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/syscall.h>
+ int lk;
+int
+main ()
+{
+syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: SYS_gettid and SYS_futex required for --enable-linux-futex" >&5
+echo "$as_me: error: SYS_gettid and SYS_futex required for --enable-linux-futex" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ;;
+ esac
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+
else
# This lets us hard-code the functionality we know we'll have in the cross
@@ -114117,6 +114325,77 @@ _ACEOF
_ACEOF
+ case "$target" in
+ *-linux*)
+ case "$enable_linux_futex" in
+ yes)
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/syscall.h>
+ int lk;
+int
+main ()
+{
+syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag"
+ || test ! -s conftest.err'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: SYS_gettid and SYS_futex required for --enable-linux-futex" >&5
+echo "$as_me: error: SYS_gettid and SYS_futex required for --enable-linux-futex" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+ ;;
+ *)
+ enable_linux_futex=no
+ ;;
+ esac
+
+fi
+
+if test x$enable_linux_futex = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LINUX_FUTEX 1
+_ACEOF
+
fi
# This depends on GLIBCXX CHECK_LINKER_FEATURES, but without it assumes no.
--- libstdc++-v3/config.h.in.jj 2007-10-19 14:39:59.000000000 +0200
+++ libstdc++-v3/config.h.in 2008-01-02 11:04:27.000000000 +0100
@@ -719,6 +719,9 @@
/* Define if a fully dynamic basic_string is wanted. */
#undef _GLIBCXX_FULLY_DYNAMIC_STRING
+/* Define if futex syscall is available. */
+#undef HAVE_LINUX_FUTEX
+
/* Define to 1 if a full hosted library is built, or 0 if freestanding. */
#undef _GLIBCXX_HOSTED
Jakub