https://gcc.gnu.org/g:4eb12ddd32d53ef55c2bd9bb03db057f096fff8f
commit r16-3668-g4eb12ddd32d53ef55c2bd9bb03db057f096fff8f Author: Nathan Myers <n...@cantrip.org> Date: Thu Aug 28 13:11:57 2025 -0400 libstdc++: Make syncbuf _S_get_mutex definition extern. This patch creates a global function __syncbuf_get_mutex, gated by _GLIBCXX_HAS_GTHREADS, replacing a static instantiated member _S_get_mutex used in syncbuf<> construction, and makes the global symbol visible. A static local table of 16 mutexes is shared among all specializations of syncbuf<>, chosen on construction by a hash of the wrapped streambuf's address. It detaches the implementation of _S_get_mutex from the C++20 ABI. libstdc++-v3/ChangeLog: * include/std/syncstream: (syncbuf<>::__mutex) Remove _S_get_mutex, use extern function instead. * src/c++20/syncbuf.cc: Define global __syncbuf_get_mutex. * src/c++20/Makefile.am: Mention syncbuf.cc. * src/c++20/Makefile.in: Regenerate. * config/abi/pre/gnu.ver: Mention mangled __syncbuf_get_mutex. Diff: --- libstdc++-v3/config/abi/pre/gnu.ver | 3 +++ libstdc++-v3/include/std/syncstream | 22 +++++------------- libstdc++-v3/src/c++20/Makefile.am | 2 +- libstdc++-v3/src/c++20/Makefile.in | 2 +- libstdc++-v3/src/c++20/syncbuf.cc | 45 +++++++++++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 18 deletions(-) diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index e1601dc39d25..2e48241d51f9 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2559,6 +2559,9 @@ GLIBCXX_3.4.35 { _ZNSt6chrono9gps_clock3nowEv; _ZNSt6chrono9tai_clock3nowEv; + # mutex& __syncbuf_get_mutex(void*) + _ZSt19__syncbuf_get_mutexPv; + # __gnu_debug::_Safe_iterator_base and _Safe_sequence_base const _ZN11__gnu_debug19_Safe_iterator_base9_M_attachEPKNS_19_Safe_sequence_baseEb; _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_singleEPKNS_19_Safe_sequence_baseEb; diff --git a/libstdc++-v3/include/std/syncstream b/libstdc++-v3/include/std/syncstream index e2b5a199ec93..92fbbdc760e7 100644 --- a/libstdc++-v3/include/std/syncstream +++ b/libstdc++-v3/include/std/syncstream @@ -46,7 +46,6 @@ #include <bits/alloc_traits.h> #include <bits/allocator.h> #include <bits/functexcept.h> -#include <bits/functional_hash.h> #include <bits/std_mutex.h> namespace std _GLIBCXX_VISIBILITY(default) @@ -199,11 +198,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __mutex { #if _GLIBCXX_HAS_GTHREADS - mutex* _M_mtx; + mutex* _M_mtx = nullptr; - __mutex(void* __t) - : _M_mtx(__t ? &_S_get_mutex(__t) : nullptr) - { } + __mutex(void* __t) // __t is the underlying sbuf, as hash seed. + { + extern mutex& __syncbuf_get_mutex(void*); // in src/c++20/syncbuf.cc + if (__t) _M_mtx = &__syncbuf_get_mutex(__t); + } void swap(__mutex& __other) noexcept @@ -220,17 +221,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _M_mtx->unlock(); } - - // FIXME: This should be put in the .so - static mutex& - _S_get_mutex(void* __t) - { - const unsigned char __mask = 0xf; - static mutex __m[__mask + 1]; - - auto __key = _Hash_impl::hash(__t) & __mask; - return __m[__key]; - } #else __mutex(void*) { } void swap(__mutex&&) noexcept { } diff --git a/libstdc++-v3/src/c++20/Makefile.am b/libstdc++-v3/src/c++20/Makefile.am index 736558ff24a7..384990aed776 100644 --- a/libstdc++-v3/src/c++20/Makefile.am +++ b/libstdc++-v3/src/c++20/Makefile.am @@ -36,7 +36,7 @@ else inst_sources = endif -sources = tzdb.cc format.cc atomic.cc clock.cc +sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc vpath % $(top_srcdir)/src/c++20 diff --git a/libstdc++-v3/src/c++20/Makefile.in b/libstdc++-v3/src/c++20/Makefile.in index 3cb6d6fea5f3..1e005ae3c14e 100644 --- a/libstdc++-v3/src/c++20/Makefile.in +++ b/libstdc++-v3/src/c++20/Makefile.in @@ -432,7 +432,7 @@ headers = @ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \ @ENABLE_EXTERN_TEMPLATE_TRUE@ sstream-inst.cc -sources = tzdb.cc format.cc atomic.cc clock.cc +sources = tzdb.cc format.cc atomic.cc clock.cc syncbuf.cc @GLIBCXX_HOSTED_FALSE@libc__20convenience_la_SOURCES = @GLIBCXX_HOSTED_TRUE@libc__20convenience_la_SOURCES = $(sources) $(inst_sources) diff --git a/libstdc++-v3/src/c++20/syncbuf.cc b/libstdc++-v3/src/c++20/syncbuf.cc new file mode 100644 index 000000000000..150ba5e3ce4d --- /dev/null +++ b/libstdc++-v3/src/c++20/syncbuf.cc @@ -0,0 +1,45 @@ +// Explicit instantiation file. + +// Copyright (C) 2020-2025 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#include <syncstream> +#include <bits/functional_hash.h> + +#if _GLIBCXX_HAS_GTHREADS +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +mutex& +__syncbuf_get_mutex(void* __t) + { + const unsigned char __mask = 0xf; + static mutex __m[__mask + 1]; + + auto __key = _Hash_impl::hash(__t) & __mask; + return __m[__key]; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} +#endif // GTHREADS