summaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-05 21:32:38 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-05 21:32:38 +0000
commit975b557313a11e8e8b83b32ac237a89c32e95a5e (patch)
tree7872cbd2d5e29eb4cc6cb620d05574769ca67a24 /libstdc++-v3
parent72211fd122a8d04d36b9ca79a8c8ea69b12dd9af (diff)
downloadgcc-975b557313a11e8e8b83b32ac237a89c32e95a5e.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147137 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog15
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver8
-rw-r--r--libstdc++-v3/include/std/mutex13
-rw-r--r--libstdc++-v3/src/mutex.cc34
-rw-r--r--libstdc++-v3/testsuite/30_threads/call_once/39909.cc56
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_abi.cc1
6 files changed, 116 insertions, 11 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b42f1799025..3ff387c17ce 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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.
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 57183c1a670..240e7bcf09b 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -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 {
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index f26acc02f4f..c090608cb53 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -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)
diff --git a/libstdc++-v3/src/mutex.cc b/libstdc++-v3/src/mutex.cc
index e0a94892158..fcc1eb97a89 100644
--- a/libstdc++-v3/src/mutex.cc
+++ b/libstdc++-v3/src/mutex.cc
@@ -28,11 +28,11 @@
#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
index 00000000000..aa125919bf8
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/call_once/39909.cc
@@ -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;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc
index e9df9f80299..ca1bb912ce5 100644
--- a/libstdc++-v3/testsuite/util/testsuite_abi.cc
+++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc
@@ -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");