Index: include/std/mutex =================================================================== --- include/std/mutex (revision 146799) +++ include/std/mutex (working copy) @@ -729,8 +729,11 @@ namespace std #else extern function __once_functor; - extern unique_lock& - __get_once_functor_lock(); + extern void + __set_once_functor_lock_ptr(unique_lock*); + + 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; #else - unique_lock& __functor_lock = __get_once_functor_lock(); - __functor_lock.lock(); + unique_lock __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) Index: src/mutex.cc =================================================================== --- src/mutex.cc (revision 146799) +++ src/mutex.cc (working copy) @@ -28,11 +28,11 @@ #ifndef _GLIBCXX_HAVE_TLS namespace { - std::mutex& - get_once_mutex() + inline std::unique_lock*& + __get_once_functor_lock_ptr() { - static std::mutex once_mutex; - return once_mutex; + static std::unique_lock* __once_functor_lock_ptr = 0; + return __once_functor_lock_ptr; } } #endif @@ -55,10 +55,25 @@ namespace std template class function; function __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* __ptr) + { + __get_once_functor_lock_ptr() = __ptr; + } + + // unsafe - retained for compatibility with ABI 3.4.11 unique_lock& __get_once_functor_lock() { - static unique_lock once_functor_lock(get_once_mutex(), defer_lock); + static unique_lock once_functor_lock(__get_once_mutex(), defer_lock); return once_functor_lock; } #endif @@ -69,7 +84,14 @@ namespace std { #ifndef _GLIBCXX_HAVE_TLS function __once_call = std::move(__once_functor); - __get_once_functor_lock().unlock(); + if (unique_lock* __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(); } Index: config/abi/pre/gnu.ver =================================================================== --- config/abi/pre/gnu.ver (revision 146799) +++ config/abi/pre/gnu.ver (working copy) @@ -882,6 +882,10 @@ GLIBCXX_3.4.11 { _ZSt23__get_once_functor_lockv; __once_proxy; + # TODO move these to new 3.4.12 block + _ZSt27__set_once_functor_lock_ptrPSt11unique_lockISt5mutexE; + _ZSt16__get_once_mutexv; + # condition_variable _ZNSt18condition_variable10notify_allEv; _ZNSt18condition_variable10notify_oneEv;