Commit efdb7347 by Jonathan Wakely Committed by Jonathan Wakely

re PR libstdc++/39909 (non-TLS version of std::call_once causes terminate)

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
parent 32f579f6
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> 2009-05-03 Jan Hubicka <jh@suse.cz>
* include/parallel/settings.h (get): Mark const. * include/parallel/settings.h (get): Mark const.
......
...@@ -958,6 +958,14 @@ GLIBCXX_3.4.11 { ...@@ -958,6 +958,14 @@ GLIBCXX_3.4.11 {
} GLIBCXX_3.4.10; } 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. # Symbols in the support library (libsupc++) have their own tag.
CXXABI_1.3 { CXXABI_1.3 {
......
...@@ -729,8 +729,11 @@ namespace std ...@@ -729,8 +729,11 @@ namespace std
#else #else
extern function<void()> __once_functor; extern function<void()> __once_functor;
extern unique_lock<mutex>& extern void
__get_once_functor_lock(); __set_once_functor_lock_ptr(unique_lock<mutex>*);
extern mutex&
__get_once_mutex();
#endif #endif
extern "C" void __once_proxy(); extern "C" void __once_proxy();
...@@ -745,16 +748,16 @@ namespace std ...@@ -745,16 +748,16 @@ namespace std
__once_callable = &__bound_functor; __once_callable = &__bound_functor;
__once_call = &__once_call_impl<decltype(__bound_functor)>; __once_call = &__once_call_impl<decltype(__bound_functor)>;
#else #else
unique_lock<mutex>& __functor_lock = __get_once_functor_lock(); unique_lock<mutex> __functor_lock(__get_once_mutex());
__functor_lock.lock();
__once_functor = bind(__f, __args...); __once_functor = bind(__f, __args...);
__set_once_functor_lock_ptr(&__functor_lock);
#endif #endif
int __e = __gthread_once(&(__once._M_once), &__once_proxy); int __e = __gthread_once(&(__once._M_once), &__once_proxy);
#ifndef _GLIBCXX_HAVE_TLS #ifndef _GLIBCXX_HAVE_TLS
if (__functor_lock) if (__functor_lock)
__functor_lock.unlock(); __set_once_functor_lock_ptr(0);
#endif #endif
if (__e) if (__e)
......
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
#ifndef _GLIBCXX_HAVE_TLS #ifndef _GLIBCXX_HAVE_TLS
namespace namespace
{ {
std::mutex& inline std::unique_lock<std::mutex>*&
get_once_mutex() __get_once_functor_lock_ptr()
{ {
static std::mutex once_mutex; static std::unique_lock<std::mutex>* __once_functor_lock_ptr = 0;
return once_mutex; return __once_functor_lock_ptr;
} }
} }
#endif #endif
...@@ -55,10 +55,25 @@ namespace std ...@@ -55,10 +55,25 @@ namespace std
template class function<void()>; template class function<void()>;
function<void()> __once_functor; 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>& unique_lock<mutex>&
__get_once_functor_lock() __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; return once_functor_lock;
} }
#endif #endif
...@@ -69,7 +84,14 @@ namespace std ...@@ -69,7 +84,14 @@ namespace std
{ {
#ifndef _GLIBCXX_HAVE_TLS #ifndef _GLIBCXX_HAVE_TLS
function<void()> __once_call = std::move(__once_functor); 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 #endif
__once_call(); __once_call();
} }
......
// { 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;
}
...@@ -183,6 +183,7 @@ check_version(symbol& test, bool added) ...@@ -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.9");
known_versions.push_back("GLIBCXX_3.4.10"); known_versions.push_back("GLIBCXX_3.4.10");
known_versions.push_back("GLIBCXX_3.4.11"); 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");
known_versions.push_back("GLIBCXX_LDBL_3.4.7"); known_versions.push_back("GLIBCXX_LDBL_3.4.7");
known_versions.push_back("GLIBCXX_LDBL_3.4.10"); known_versions.push_back("GLIBCXX_LDBL_3.4.10");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment