This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch master updated. glibc-2.22-329-g99e1dc0


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  99e1dc0a688d6c25d3f422bc9f3fa29adb483339 (commit)
      from  6c9678ebd42358f931100130a368fafe375a0ba2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=99e1dc0a688d6c25d3f422bc9f3fa29adb483339

commit 99e1dc0a688d6c25d3f422bc9f3fa29adb483339
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Oct 6 21:27:55 2015 +0200

    Add a test case for C++11 thread_local support
    
    This requires a C++ compiler with thread_local support, and a new
    configure check is needed.

diff --git a/ChangeLog b/ChangeLog
index 9b762b3..ddbd26d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2015-10-06  Florian Weimer  <fweimer@redhat.com>
+
+	* configure.ac (libc_cv_cxx_thread_local): Define.
+	* configure: Regenerate.
+	* config.make.in (have-cxx-thread_local): Define.
+	* nptl/Makefile (CFLAGS-tst-thread_local1.o):
+	(LDLIBS-tst-thread_local1): Define.
+	(tests): Add tst-thread_local1.
+	[have-cxx-thread_local != yes] (tests-unsupported): Add
+	tst-thread_local1.
+	* nptl/tst-thread_local1.cc: New file.
+
 2015-10-06  Joseph Myers  <joseph@codesourcery.com>
 
 	[BZ #19078]
diff --git a/config.make.in b/config.make.in
index bea371d..839d86f 100644
--- a/config.make.in
+++ b/config.make.in
@@ -68,6 +68,7 @@ bind-now = @bindnow@
 have-hash-style = @libc_cv_hashstyle@
 use-default-link = @use_default_link@
 output-format = @libc_cv_output_format@
+have-cxx-thread_local = @libc_cv_cxx_thread_local@
 
 static-libgcc = @libc_cv_gcc_static_libgcc@
 
diff --git a/configure b/configure
index fe402ea..f0cd175 100755
--- a/configure
+++ b/configure
@@ -614,6 +614,7 @@ use_nscd
 libc_cv_gcc_unwind_find_fde
 libc_extra_cppflags
 libc_extra_cflags
+libc_cv_cxx_thread_local
 CPPUNDEFS
 sizeof_long_double
 have_selinux
@@ -7215,6 +7216,61 @@ if test $libc_cv_builtin_trap = yes; then
 
 fi
 
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler supports thread_local" >&5
+$as_echo_n "checking whether the C++ compiler supports thread_local... " >&6; }
+if ${libc_cv_cxx_thread_local+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+old_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=gnu++11"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <thread>
+
+// Compiler support.
+struct S
+{
+  S ();
+  ~S ();
+};
+thread_local S s;
+S * get () { return &s; }
+
+// libstdc++ support.
+#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
+#error __cxa_thread_atexit_impl not supported
+#endif
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  libc_cv_cxx_thread_local=yes
+else
+  libc_cv_cxx_thread_local=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CXXFLAGS="$old_CXXFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_cxx_thread_local" >&5
+$as_echo "$libc_cv_cxx_thread_local" >&6; }
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
 ### End of automated tests.
 ### Now run sysdeps configure fragments.
 
diff --git a/configure.ac b/configure.ac
index 95d700e..75a3a77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1982,6 +1982,39 @@ if test $libc_cv_builtin_trap = yes; then
   AC_DEFINE([HAVE_BUILTIN_TRAP])
 fi
 
+dnl C++ feature tests.
+AC_LANG_PUSH([C++])
+
+AC_CACHE_CHECK([whether the C++ compiler supports thread_local],
+	       libc_cv_cxx_thread_local, [
+old_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -std=gnu++11"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <thread>
+
+// Compiler support.
+struct S
+{
+  S ();
+  ~S ();
+};
+thread_local S s;
+S * get () { return &s; }
+
+// libstdc++ support.
+#ifndef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL
+#error __cxa_thread_atexit_impl not supported
+#endif
+])],
+	       [libc_cv_cxx_thread_local=yes],
+	       [libc_cv_cxx_thread_local=no])
+CXXFLAGS="$old_CXXFLAGS"
+])
+AC_SUBST(libc_cv_cxx_thread_local)
+
+AC_LANG_POP([C++])
+dnl End of C++ feature tests.
+
 ### End of automated tests.
 ### Now run sysdeps configure fragments.
 
diff --git a/nptl/Makefile b/nptl/Makefile
index aaca0a4..f3de49b 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -212,6 +212,8 @@ CFLAGS-recvfrom.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pt-system.c = -fexceptions
 
 LDLIBS-tst-once5 = -lstdc++
+CFLAGS-tst-thread_local1.o = -std=gnu++11
+LDLIBS-tst-thread_local1 = -lstdc++
 
 tests = tst-typesizes \
 	tst-attr1 tst-attr2 tst-attr3 tst-default-attr \
@@ -283,7 +285,8 @@ tests = tst-typesizes \
 	tst-getpid3 \
 	tst-setuid3 \
 	tst-initializers1 $(addprefix tst-initializers1-,c89 gnu89 c99 gnu99) \
-	tst-bad-schedattr
+	tst-bad-schedattr \
+	tst-thread_local1
 xtests = tst-setuid1 tst-setuid1-static tst-setuid2 \
 	tst-mutexpp1 tst-mutexpp6 tst-mutexpp10
 test-srcs = tst-oddstacklimit
@@ -403,6 +406,10 @@ ifeq (,$(CXX))
 # These tests require a C++ compiler and runtime.
 tests-unsupported += tst-cancel24 tst-cancel24-static tst-once5
 endif
+# These tests require a C++ compiler and runtime with thread_local support.
+ifneq ($(have-cxx-thread_local),yes)
+tests-unsupported += tst-thread_local1
+endif
 
 include ../Rules
 
diff --git a/nptl/tst-thread_local1.cc b/nptl/tst-thread_local1.cc
new file mode 100644
index 0000000..133cc27
--- /dev/null
+++ b/nptl/tst-thread_local1.cc
@@ -0,0 +1,199 @@
+/* Test basic thread_local support.
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <functional>
+#include <string>
+#include <thread>
+
+struct counter
+{
+  int constructed {};
+  int destructed {};
+
+  void reset ();
+};
+
+void
+counter::reset ()
+{
+  constructed = 0;
+  destructed = 0;
+}
+
+static std::string
+to_string (const counter &c)
+{
+  char buf[128];
+  snprintf (buf, sizeof (buf), "%d/%d",
+            c.constructed, c.destructed);
+  return buf;
+}
+
+template <counter *Counter>
+struct counting
+{
+  counting () __attribute__ ((noinline, noclone));
+  ~counting () __attribute__ ((noinline, noclone));
+  void operation () __attribute__ ((noinline, noclone));
+};
+
+template<counter *Counter>
+__attribute__ ((noinline, noclone))
+counting<Counter>::counting ()
+{
+  ++Counter->constructed;
+}
+
+template<counter *Counter>
+__attribute__ ((noinline, noclone))
+counting<Counter>::~counting ()
+{
+  ++Counter->destructed;
+}
+
+template<counter *Counter>
+void __attribute__ ((noinline, noclone))
+counting<Counter>::operation ()
+{
+  // Optimization barrier.
+  asm ("");
+}
+
+static counter counter_static;
+static counter counter_anonymous_namespace;
+static counter counter_extern;
+static counter counter_function_local;
+static bool errors (false);
+
+static std::string
+all_counters ()
+{
+  return to_string (counter_static)
+    + ' ' + to_string (counter_anonymous_namespace)
+    + ' ' + to_string (counter_extern)
+    + ' ' + to_string (counter_function_local);
+}
+
+static void
+check_counters (const char *name, const char *expected)
+{
+  std::string actual{all_counters ()};
+  if (actual != expected)
+    {
+      printf ("error: %s: (%s) != (%s)\n",
+              name, actual.c_str (), expected);
+      errors = true;
+    }
+}
+
+static void
+reset_all ()
+{
+  counter_static.reset ();
+  counter_anonymous_namespace.reset ();
+  counter_extern.reset ();
+  counter_function_local.reset ();
+}
+
+static thread_local counting<&counter_static> counting_static;
+namespace {
+  thread_local counting<&counter_anonymous_namespace>
+    counting_anonymous_namespace;
+}
+extern thread_local counting<&counter_extern> counting_extern;
+thread_local counting<&counter_extern> counting_extern;
+
+static void *
+thread_without_access (void *)
+{
+  return nullptr;
+}
+
+static void *
+thread_with_access (void *)
+{
+  thread_local counting<&counter_function_local> counting_function_local;
+  counting_function_local.operation ();
+  check_counters ("early in thread_with_access", "0/0 0/0 0/0 1/0");
+  counting_static.operation ();
+  counting_anonymous_namespace.operation ();
+  counting_extern.operation ();
+  check_counters ("in thread_with_access", "1/0 1/0 1/0 1/0");
+  return nullptr;
+}
+
+static int
+do_test (void)
+{
+  std::function<void (void *(void *))> do_pthread =
+    [](void *(func) (void *))
+    {
+      pthread_t thr;
+      int ret = pthread_create (&thr, nullptr, func, nullptr);
+      if (ret != 0)
+        {
+          errno = ret;
+          printf ("error: pthread_create: %m\n");
+          errors = true;
+          return;
+        }
+      ret = pthread_join (thr, nullptr);
+      if (ret != 0)
+        {
+          errno = ret;
+          printf ("error: pthread_join: %m\n");
+          errors = true;
+          return;
+        }
+    };
+  std::function<void (void *(void *))> do_std_thread =
+    [](void *(func) (void *))
+    {
+      std::thread thr{[func] {func (nullptr);}};
+      thr.join ();
+    };
+
+  std::array<std::pair<const char *, std::function<void (void *(void *))>>, 2>
+    do_thread_X
+      {{
+        {"pthread_create", do_pthread},
+        {"std::thread", do_std_thread},
+      }};
+
+  for (auto do_thread : do_thread_X)
+    {
+      printf ("info: testing %s\n", do_thread.first);
+      check_counters ("initial", "0/0 0/0 0/0 0/0");
+      do_thread.second (thread_without_access);
+      check_counters ("after thread_without_access", "0/0 0/0 0/0 0/0");
+      reset_all ();
+      do_thread.second (thread_with_access);
+      check_counters ("after thread_with_access", "1/1 1/1 1/1 1/1");
+      reset_all ();
+    }
+
+  return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                 |   12 +++
 config.make.in            |    1 +
 configure                 |   56 +++++++++++++
 configure.ac              |   33 ++++++++
 nptl/Makefile             |    9 ++-
 nptl/tst-thread_local1.cc |  199 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 309 insertions(+), 1 deletions(-)
 create mode 100644 nptl/tst-thread_local1.cc


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]