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