re PR libstdc++/39909 (non-TLS version of std::call_once causes terminate)
authorJonathan Wakely <jwakely.gcc@gmail.com>
Tue, 5 May 2009 21:32:38 +0000 (21:32 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 5 May 2009 21:32:38 +0000 (22:32 +0100)
2009-05-05  Jonathan Wakely  <jwakely.gcc@gmail.com>

PR libstdc++/39909
* include/std/mutex (__get_once_functor_lock, __get_once_mutex,
__set_once_functor_lock_ptr): Replace global lock object with local
locks on global mutex.
* src/mutex.cc (__get_once_functor_lock, __get_once_mutex,
__set_once_functor_lock_ptr): Likewise, keeping old function to
preserve ABI.
(__once_proxy): Use pointer to local lock if set, global lock
otherwise.
* config/abi/pre/gnu.ver: Add new symbols to new ABI version.
* testsuite/util/testsuite_abi.cc: Add GLIBCX_3.4.12 version.
* testsuite/30_threads/call_once/39909.cc: New.

From-SVN: r147137

libstdc++-v3/ChangeLog
libstdc++-v3/config/abi/pre/gnu.ver
libstdc++-v3/include/std/mutex
libstdc++-v3/src/mutex.cc
libstdc++-v3/testsuite/30_threads/call_once/39909.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_abi.cc

index b42f179..3ff387c 100644 (file)
@@ -1,3 +1,18 @@
+2009-05-05  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       PR libstdc++/39909
+       * include/std/mutex (__get_once_functor_lock, __get_once_mutex,
+       __set_once_functor_lock_ptr): Replace global lock object with local
+       locks on global mutex.
+       * src/mutex.cc (__get_once_functor_lock, __get_once_mutex,
+       __set_once_functor_lock_ptr): Likewise, keeping old function to
+       preserve ABI.
+       (__once_proxy): Use pointer to local lock if set, global lock
+       otherwise.
+       * config/abi/pre/gnu.ver: Add new symbols to new ABI version.
+       * testsuite/util/testsuite_abi.cc: Add GLIBCX_3.4.12 version.
+       * testsuite/30_threads/call_once/39909.cc: New.
+
 2009-05-03  Jan Hubicka  <jh@suse.cz>
 
        * include/parallel/settings.h (get): Mark const.
index 57183c1..240e7bc 100644 (file)
@@ -958,6 +958,14 @@ GLIBCXX_3.4.11 {
 
 } GLIBCXX_3.4.10;
 
+GLIBCXX_3.4.12 {
+
+    # mutex
+    _ZSt27__set_once_functor_lock_ptrPSt11unique_lockISt5mutexE;
+    _ZSt16__get_once_mutexv;
+
+} GLIBCXX_3.4.11;
+
 # Symbols in the support library (libsupc++) have their own tag.
 CXXABI_1.3 {
 
index f26acc0..c090608 100644 (file)
@@ -729,8 +729,11 @@ namespace std
 #else
   extern function<void()> __once_functor;
 
-  extern unique_lock<mutex>&
-  __get_once_functor_lock();
+  extern void
+  __set_once_functor_lock_ptr(unique_lock<mutex>*);
+
+  extern mutex&
+  __get_once_mutex();
 #endif
 
   extern "C" void __once_proxy();
@@ -745,16 +748,16 @@ namespace std
       __once_callable = &__bound_functor;
       __once_call = &__once_call_impl<decltype(__bound_functor)>;
 #else
-      unique_lock<mutex>& __functor_lock = __get_once_functor_lock();
-      __functor_lock.lock();
+      unique_lock<mutex> __functor_lock(__get_once_mutex());
       __once_functor = bind(__f, __args...);
+      __set_once_functor_lock_ptr(&__functor_lock);
 #endif
 
       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
 
 #ifndef _GLIBCXX_HAVE_TLS
       if (__functor_lock)
-       __functor_lock.unlock();
+        __set_once_functor_lock_ptr(0);
 #endif
 
       if (__e)
index e0a9489..fcc1eb9 100644 (file)
 #ifndef _GLIBCXX_HAVE_TLS
 namespace
 {
-  std::mutex&
-  get_once_mutex()
+  inline std::unique_lock<std::mutex>*&
+  __get_once_functor_lock_ptr()
   {
-    static std::mutex once_mutex;
-    return once_mutex;
+    static std::unique_lock<std::mutex>* __once_functor_lock_ptr = 0;
+    return __once_functor_lock_ptr;
   }
 }
 #endif
@@ -55,10 +55,25 @@ namespace std
   template class function<void()>;
   function<void()> __once_functor;
 
+  mutex&
+  __get_once_mutex()
+  {
+    static mutex once_mutex;
+    return once_mutex;
+  }
+
+  // code linked against ABI 3.4.12 and later uses this
+  void
+  __set_once_functor_lock_ptr(unique_lock<mutex>* __ptr)
+  {
+    __get_once_functor_lock_ptr() = __ptr;
+  }
+
+  // unsafe - retained for compatibility with ABI 3.4.11
   unique_lock<mutex>&
   __get_once_functor_lock()
   {
-    static unique_lock<mutex> once_functor_lock(get_once_mutex(), defer_lock);
+    static unique_lock<mutex> once_functor_lock(__get_once_mutex(), defer_lock);
     return once_functor_lock;
   }
 #endif
@@ -69,7 +84,14 @@ namespace std
     {
 #ifndef _GLIBCXX_HAVE_TLS
       function<void()> __once_call = std::move(__once_functor);
-      __get_once_functor_lock().unlock();
+      if (unique_lock<mutex>* __lock = __get_once_functor_lock_ptr())
+      {
+        // caller is using new ABI and provided lock ptr
+        __get_once_functor_lock_ptr() = 0;
+        __lock->unlock();
+      }
+      else
+        __get_once_functor_lock().unlock();  // global lock
 #endif
       __once_call();
     }
diff --git a/libstdc++-v3/testsuite/30_threads/call_once/39909.cc b/libstdc++-v3/testsuite/30_threads/call_once/39909.cc
new file mode 100644 (file)
index 0000000..aa12591
--- /dev/null
@@ -0,0 +1,56 @@
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+
+// Copyright (C) 2009 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
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+
+#include <mutex>
+#include <thread>
+#include <testsuite_hooks.h>
+
+std::once_flag flag;
+int value = 0;
+
+struct Inc { void operator()() const { ++value; } };
+
+struct Func
+{
+   void operator()() const
+   {
+       Inc inc;
+       for (int i = 0; i < 10000;  ++i)
+           std::call_once(flag, inc);
+   }
+};
+
+int main()
+{
+   Func f;
+   std::thread t1(f);
+   std::thread t2(f);
+   std::thread t3(f);
+   t1.join();
+   t2.join();
+   t3.join();
+   VERIFY( value == 1 );
+   return 0;
+}
index e9df9f8..ca1bb91 100644 (file)
@@ -183,6 +183,7 @@ check_version(symbol& test, bool added)
       known_versions.push_back("GLIBCXX_3.4.9");
       known_versions.push_back("GLIBCXX_3.4.10");
       known_versions.push_back("GLIBCXX_3.4.11");
+      known_versions.push_back("GLIBCXX_3.4.12");
       known_versions.push_back("GLIBCXX_LDBL_3.4");
       known_versions.push_back("GLIBCXX_LDBL_3.4.7");
       known_versions.push_back("GLIBCXX_LDBL_3.4.10");