From 0f3e711eef24f6b00e7dc462288c064d68a9ec43 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 8 Jan 2008 17:14:49 +0100 Subject: [PATCH] configure.ac (--enable-linux-futex): Add new configure option. libstdc++-v3/ * configure.ac (--enable-linux-futex): Add new configure option. (HAVE_LINUX_FUTEX): New AC_DEFINE. * Makefile.in: Rebuilt. * aclocal.m4: Rebuilt. * 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. config/ * futex.m4: New file. libgomp/ * configure.ac: Move futex checking into ../config/futex.m4. * configure: Rebuilt. * aclocal.m4: Rebuilt. * Makefile.in: Rebuilt. * configure.tgt: Rename have_tls to gcc_cv_have_tls to match 2007-10-15 ../config/tls.m4 change. From-SVN: r131399 --- config/ChangeLog | 4 + config/futex.m4 | 64 ++++++ libgomp/ChangeLog | 10 + libgomp/Makefile.in | 3 +- libgomp/aclocal.m4 | 1 + libgomp/configure | 58 +++-- libgomp/configure.ac | 50 +--- libgomp/configure.tgt | 2 +- libstdc++-v3/ChangeLog | 20 ++ libstdc++-v3/Makefile.in | 1 + libstdc++-v3/aclocal.m4 | 1 + libstdc++-v3/config.h.in | 3 + libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h | 8 +- .../config/cpu/generic/cxxabi_tweaks.h | 5 +- libstdc++-v3/configure | 216 ++++++++++++++++++ libstdc++-v3/configure.ac | 3 +- libstdc++-v3/libsupc++/guard.cc | 133 +++++++++-- 17 files changed, 486 insertions(+), 96 deletions(-) create mode 100644 config/futex.m4 diff --git a/config/ChangeLog b/config/ChangeLog index 77082b4a3e1..8343f066a86 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,7 @@ +2008-01-08 Jakub Jelinek + + * futex.m4: New file. + 2007-12-06 Richard Sandiford * mt-sde (CFLAGS_FOR_TARGET, CXXFLAGS_FOR_TARGET): Use +=, not =. diff --git a/config/futex.m4 b/config/futex.m4 new file mode 100644 index 00000000000..e95144dd16a --- /dev/null +++ b/config/futex.m4 @@ -0,0 +1,64 @@ +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libgomp. + +dnl +dnl GCC_LINUX_FUTEX +dnl (SHELL-CODE_HANDLER) +dnl +AC_DEFUN([GCC_LINUX_FUTEX],[dnl +GCC_ENABLE(linux-futex,default, ,[use the Linux futex system call], + permit yes|no|default) +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 + 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_t th; void *status;], + [pthread_tryjoin_np (th, &status);])],[enable_linux_futex=yes], + [if test x$cross_compiling = xno; then + 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 + fi + enable_linux_futex=yes]) + LIBS="$save_LIBS"]) + ;; + yes) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include + 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 +if test x$enable_linux_futex = xyes; then + $1 +fi +]) diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 0ef0abf7386..cf698662bdf 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,13 @@ +2008-01-08 Jakub Jelinek + + * configure.ac: Move futex checking into ../config/futex.m4. + * configure: Rebuilt. + * aclocal.m4: Rebuilt. + * Makefile.in: Rebuilt. + + * configure.tgt: Rename have_tls to gcc_cv_have_tls to match + 2007-10-15 ../config/tls.m4 change. + 2007-12-19 Jakub Jelinek PR c++/34513 diff --git a/libgomp/Makefile.in b/libgomp/Makefile.in index bfc558c2e51..6ba3dcc9a28 100644 --- a/libgomp/Makefile.in +++ b/libgomp/Makefile.in @@ -55,7 +55,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/lead-dot.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/stdint.m4 \ - $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../config/tls.m4 \ + $(top_srcdir)/../config/futex.m4 $(top_srcdir)/../ltoptions.m4 \ $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac diff --git a/libgomp/aclocal.m4 b/libgomp/aclocal.m4 index 505095df94c..1746f255949 100644 --- a/libgomp/aclocal.m4 +++ b/libgomp/aclocal.m4 @@ -863,6 +863,7 @@ m4_include([../config/lead-dot.m4]) m4_include([../config/multi.m4]) m4_include([../config/stdint.m4]) m4_include([../config/tls.m4]) +m4_include([../config/futex.m4]) m4_include([../ltoptions.m4]) m4_include([../ltsugar.m4]) m4_include([../ltversion.m4]) diff --git a/libgomp/configure b/libgomp/configure index cb78249f4cd..391a81946f4 100755 --- a/libgomp/configure +++ b/libgomp/configure @@ -1003,8 +1003,6 @@ Optional Features: --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory [default=no] - --enable-linux-futex Use the Linux futex system call - [default=default] --enable-generated-files-in-srcdir put copies of generated files in source dir intended for creating source tarballs for users without @@ -1021,6 +1019,8 @@ Optional Features: --disable-libtool-lock avoid locking (might break parallel builds) --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer + --enable-linux-futex use the Linux futex system call + [default=default] --enable-tls Use thread-local storage [default=yes] --enable-symvers=STYLE enables symbol versioning of the shared library [default=yes] @@ -1518,26 +1518,6 @@ fi; echo "$as_me:$LINENO: result: $enable_version_specific_runtime_libs" >&5 echo "${ECHO_T}$enable_version_specific_runtime_libs" >&6 -echo "$as_me:$LINENO: checking for --enable-linux-futex" >&5 -echo $ECHO_N "checking for --enable-linux-futex... $ECHO_C" >&6 - # 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; - -echo "$as_me:$LINENO: result: $enable_linux_futex" >&5 -echo "${ECHO_T}$enable_linux_futex" >&6 - # We would like our source tree to be readonly. However when releases or # pre-releases are generated, the flex/bison generated files as well as the # various formats of manuals need to be included along with the rest of the @@ -16661,6 +16641,24 @@ cat >>confdefs.h <<\_ACEOF _ACEOF ;; +esac + + # 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; + +case "$target" in *-linux*) case "$enable_linux_futex" in default) @@ -16709,7 +16707,9 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - cat >conftest.$ac_ext <<_ACEOF + save_LIBS="$LIBS" + LIBS="-lpthread $LIBS" + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext @@ -16757,7 +16757,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 if test x$cross_compiling = xno; then if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null \ - | LC_ALL=C grep -i NPTL > /dev/null 2>/dev/null; then + | 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. @@ -16768,6 +16768,7 @@ If so, please configure with --disable-linux-futex" >&2;} 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 @@ -16776,7 +16777,7 @@ fi rm -f conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ;; - yes) + yes) cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF @@ -16829,7 +16830,14 @@ rm -f conftest.err conftest.$ac_objext \ ;; esac ;; + *) + enable_linux_futex=no + ;; esac +if test x$enable_linux_futex = xyes; then + : +fi + # Check for pthread_{,attr_}[sg]etaffinity_np. cat >conftest.$ac_ext <<_ACEOF diff --git a/libgomp/configure.ac b/libgomp/configure.ac index 68a18e17561..0cda749d593 100644 --- a/libgomp/configure.ac +++ b/libgomp/configure.ac @@ -15,12 +15,6 @@ LIBGOMP_ENABLE(version-specific-runtime-libs, no, , permit yes|no) AC_MSG_RESULT($enable_version_specific_runtime_libs) -AC_MSG_CHECKING([for --enable-linux-futex]) -LIBGOMP_ENABLE(linux-futex, default, , - [Use the Linux futex system call], - permit yes|no|default) -AC_MSG_RESULT($enable_linux_futex) - # We would like our source tree to be readonly. However when releases or # pre-releases are generated, the flex/bison generated files as well as the # various formats of manuals need to be included along with the rest of the @@ -192,50 +186,10 @@ case "$host" in AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1, Define if the POSIX Semaphores do not work on your system.) ;; - *-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 - int lk;], - [syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0);])], - [AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [#ifndef _GNU_SOURCE - #define _GNU_SOURCE 1 - #endif - #include - pthread_t th; void *status;], - [pthread_tryjoin_np (th, &status);])],[enable_linux_futex=yes], - [if test x$cross_compiling = xno; then - if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null \ - | LC_ALL=C grep -i NPTL > /dev/null 2>/dev/null; then - AC_MSG_WARN([The kernel might not support futex or gettid syscalls. -If so, please configure with --disable-linux-futex]) - fi - fi - enable_linux_futex=yes])]) - ;; - yes) - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [#include - 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 - ;; esac +GCC_LINUX_FUTEX(:) + # Check for pthread_{,attr_}[sg]etaffinity_np. AC_LINK_IFELSE( [AC_LANG_PROGRAM( diff --git a/libgomp/configure.tgt b/libgomp/configure.tgt index f46210c3647..68115abf71d 100644 --- a/libgomp/configure.tgt +++ b/libgomp/configure.tgt @@ -11,7 +11,7 @@ # XLDFLAGS Add extra link flags to use. # Optimize TLS usage by avoiding the overhead of dynamic allocation. -if test $have_tls = yes ; then +if test $gcc_cv_have_tls = yes ; then case "${target}" in *-*-linux*) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e99e0500360..a5b54c46608 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,23 @@ +2008-01-08 Jakub Jelinek + + * configure.ac (--enable-linux-futex): Add new configure option. + (HAVE_LINUX_FUTEX): New AC_DEFINE. + * Makefile.in: Rebuilt. + * aclocal.m4: Rebuilt. + * 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. + 2008-01-07 Paolo Carlini PR libstdc++/34680 diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in index c3d4cc592e0..75241af5f5d 100644 --- a/libstdc++-v3/Makefile.in +++ b/libstdc++-v3/Makefile.in @@ -54,6 +54,7 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/enable.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ + $(top_srcdir)/../config/futex.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ $(top_srcdir)/crossconfig.m4 $(top_srcdir)/linkage.m4 \ diff --git a/libstdc++-v3/aclocal.m4 b/libstdc++-v3/aclocal.m4 index 66a69892520..02b6b899cd5 100644 --- a/libstdc++-v3/aclocal.m4 +++ b/libstdc++-v3/aclocal.m4 @@ -589,6 +589,7 @@ m4_include([../config/lib-prefix.m4]) m4_include([../config/multi.m4]) m4_include([../config/no-executables.m4]) m4_include([../config/unwind_ipinfo.m4]) +m4_include([../config/futex.m4]) m4_include([../libtool.m4]) m4_include([../ltoptions.m4]) m4_include([../ltsugar.m4]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 1c7bcd3f9cc..f25ab541dff 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -232,6 +232,9 @@ /* Only used in build directory testsuite_hooks.h. */ #undef HAVE_LIMIT_VMEM +/* Define if futex syscall is available. */ +#undef HAVE_LINUX_FUTEX + /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H diff --git a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h index e56c20067ca..b6b88e41431 100644 --- a/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h +++ b/libstdc++-v3/config/cpu/arm/cxxabi_tweaks.h @@ -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 (2, 1) 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 (2, 1) __extension__ typedef int __guard __attribute__((mode (__DI__))); // __cxa_vec_ctor has void return type. diff --git a/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h b/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h index 95fd3066c04..2859e83c9be 100644 --- a/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h +++ b/libstdc++-v3/config/cpu/generic/cxxabi_tweaks.h @@ -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 (2, 1) __extension__ typedef int __guard __attribute__((mode (__DI__))); // __cxa_vec_ctor has void return type. diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 5e57fd651c6..403b8183bbe 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -1053,6 +1053,8 @@ Optional Features: memory [default=no] --enable-tls Use thread-local storage [default=yes] --disable-rpath do not hardcode runtime library paths + --enable-linux-futex use the Linux futex system call + [default=default] --enable-symvers=STYLE enables symbol versioning of the shared library [default=yes] --enable-visibility enables visibility safe usage [default=yes] @@ -114116,8 +114118,222 @@ _ACEOF #define HAVE_GETIPINFO 1 _ACEOF +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; + +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 + 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_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 test x$cross_compiling = xno; then + 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 + 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 + 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 +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. diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 72471f15795..3411b97afc8 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -295,9 +295,10 @@ else # Assume we have _Unwind_GetIPInfo for cross-compiles. AC_DEFINE(HAVE_GETIPINFO) - fi +GCC_LINUX_FUTEX([AC_DEFINE(HAVE_LINUX_FUTEX, 1, [Define if futex syscall is available.])]) + # This depends on GLIBCXX CHECK_LINKER_FEATURES, but without it assumes no. GLIBCXX_ENABLE_SYMVERS([yes]) GLIBCXX_ENABLE_VISIBILITY([yes]) diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc index 6cf83b1c1f4..e4665773ca2 100644 --- a/libstdc++-v3/libsupc++/guard.cc +++ b/libstdc++-v3/libsupc++/guard.cc @@ -35,12 +35,21 @@ #include #include #include +#if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \ + && defined(_GLIBCXX_ATOMIC_BUILTINS) && defined(_GLIBCXX_HAVE_LINUX_FUTEX) +# include +# include +# 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 *g) _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,20 @@ 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 waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; + int old = __sync_lock_test_and_set (gi, 0); + + if ((old & waiting_bit) != 0) + syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX); + return; + } +#elif defined(__GTHREAD_HAS_COND) if (__gthread_active_p()) { mutex_wrapper mw; @@ -293,7 +376,21 @@ 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 waiting_bit = _GLIBCXX_GUARD_WAITING_BIT; + int old = __sync_lock_test_and_set (gi, guard_bit); + + if ((old & waiting_bit) != 0) + syscall (SYS_futex, gi, _GLIBCXX_FUTEX_WAKE, INT_MAX); + return; + } +#elif defined(__GTHREAD_HAS_COND) if (__gthread_active_p()) { mutex_wrapper mw;