This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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]

Re: std::call_once without TLS


2009/4/4 Jonathan Wakely:
>> A build with --disable-tls causes this new test to fail in
>> unique_lock::lock() when a second thread tries to lock the global
>> mutex that is already locked.
>>
>> Tested x86-64-unknown-linux-gnu with --disable-tls, ok for trunk and 4.4?


Patch updated for current trunk and retested. OK for trunk?

        * include/std/mutex (__get_once_functor_lock, __get_once_mutex):
        Replace global lock object with local locks on global mutex.
        * src/mutex.cc: Likewise.
        * config/abi/pre/gnu.ver: Adjust.
        * testsuite/30_threads/call_once/call_once2.cc: New.

Jonathan
Index: include/std/mutex
===================================================================
--- include/std/mutex	(revision 146602)
+++ include/std/mutex	(working copy)
@@ -728,9 +728,10 @@ namespace std
     }
 #else
   extern function<void()> __once_functor;
+  extern unique_lock<mutex>* __once_functor_lock;
 
-  extern unique_lock<mutex>&
-  __get_once_functor_lock();
+  extern mutex&
+  __get_once_mutex();
 #endif
 
   extern "C" void __once_proxy();
@@ -745,18 +746,13 @@ 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...);
+      __once_functor_lock = &__functor_lock;
 #endif
 
       int __e = __gthread_once(&(__once._M_once), &__once_proxy);
 
-#ifndef _GLIBCXX_HAVE_TLS
-      if (__functor_lock)
-	__functor_lock.unlock();
-#endif
-
       if (__e)
 	__throw_system_error(__e);
     }
Index: src/mutex.cc
===================================================================
--- src/mutex.cc	(revision 146602)
+++ src/mutex.cc	(working copy)
@@ -25,18 +25,6 @@
 #include <mutex>
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
-#ifndef _GLIBCXX_HAVE_TLS
-namespace
-{
-  std::mutex&
-  get_once_mutex()
-  {
-    static std::mutex once_mutex;
-    return once_mutex;
-  }
-}
-#endif
-
 namespace std
 {
   const defer_lock_t defer_lock = defer_lock_t();
@@ -55,11 +43,13 @@ namespace std
   template class function<void()>;
   function<void()> __once_functor;
 
-  unique_lock<mutex>&
-  __get_once_functor_lock()
+  unique_lock<mutex>* __once_functor_lock;
+
+  mutex&
+  __get_once_mutex()
   {
-    static unique_lock<mutex> once_functor_lock(get_once_mutex(), defer_lock);
-    return once_functor_lock;
+    static mutex once_mutex;
+    return once_mutex;
   }
 #endif
 
@@ -69,7 +59,7 @@ namespace std
     {
 #ifndef _GLIBCXX_HAVE_TLS
       function<void()> __once_call = std::move(__once_functor);
-      __get_once_functor_lock().unlock();
+      __once_functor_lock->unlock();
 #endif
       __once_call();
     }
Index: config/abi/pre/gnu.ver
===================================================================
--- config/abi/pre/gnu.ver	(revision 146602)
+++ config/abi/pre/gnu.ver	(working copy)
@@ -879,7 +879,8 @@ GLIBCXX_3.4.11 {
     _ZSt11__once_call;
     _ZSt15__once_callable;
     _ZSt14__once_functor;
-    _ZSt23__get_once_functor_lockv;
+    _ZSt19__once_functor_lock;
+    _ZSt16__get_once_mutexv;
     __once_proxy;
 
     # condition_variable
Index: testsuite/30_threads/call_once/call_once2.cc
===================================================================
--- testsuite/30_threads/call_once/call_once2.cc	(revision 0)
+++ testsuite/30_threads/call_once/call_once2.cc	(revision 0)
@@ -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]