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
This commit is contained in:
parent
32f579f6eb
commit
efdb734755
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue