From 637e3668fdc17c4e226538fb14f9fab225433d01 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 5 Oct 2022 21:21:54 +0100 Subject: [PATCH] libstdc++: Allow emergency EH alloc pool size to be tuned [PR68606] Implement a long-standing request to support tuning the size of the emergency buffer for allocating exceptions after malloc fails, or to disable that buffer entirely. It's now possible to disable the dynamic allocation of the buffer and use a fixed-size static buffer, via --enable-libstdcxx-static-eh-pool. This is a built-time choice that is baked into libstdc++ and so affects all code linked against that build of libstdc++. The size of the pool can be set by --with-libstdcxx-eh-pool-obj-count=N which is measured in units of sizeof(void*) not bytes. A given exception type such as std::system_error depends on the target, so giving a size in bytes wouldn't be portable across 16/32/64-bit targets. When libstdc++ is configured to use a dynamic buffer, the size of that buffer can now be tuned at runtime by setting the GLIBCXX_TUNABLES environment variable (c.f. PR libstdc++/88264). The number of exceptions to reserve space for is controlled by the "glibcxx.eh_pool.obj_count" and "glibcxx.eh_pool.obj_size" tunables. The pool will be sized to be able to allocate obj_count exceptions of size obj_size*sizeof(void*) and obj_count "dependent" exceptions rethrown by std::rethrow_exception. With the ability to tune the buffer size, we can reduce the default pool size on 32-bit and 16-bit targets. Most users never need to throw 1kB exceptions in parallel from hundreds of threads after malloc is OOM. The users who do need that can use the tunables to select larger sizes. The old defaults can be chosen at runtime by setting GLIBCXX_TUNABLES to: 64-bit: glibcxx.eh_pool.obj_count=64:glibcxx.eh_pool.obj_size=112 32-bit: glibcxx.eh_pool.obj_count=32:glibcxx.eh_pool.obj_size=104 Or approximated by configuring with: 64-bit: --with-libstdcxx-eh-pool-obj-count=252 32-bit: --with-libstdcxx-eh-pool-obj-count=94 libstdc++-v3/ChangeLog: PR libstdc++/68606 * Makefile.in: Regenerate. * acinclude.m4 (GLIBCXX_EMERGENCY_EH_ALLOC): New macro. * configure: Regenerate. * configure.ac: Use GLIBCXX_EMERGENCY_EH_ALLOC. * crossconfig.m4: Check for secure_getenv. * doc/Makefile.in: Regenerate. * doc/xml/manual/configure.xml: Document new configure options. * doc/xml/manual/evolution.xml: Document addition of tunables. * doc/xml/manual/using_exceptions.xml: Document emergency buffer and tunables. * doc/html/*: Regenerate. * include/Makefile.in: Regenerate. * libsupc++/Makefile.am: Use EH_POOL_FLAGS. * libsupc++/Makefile.in: Regenerate. * libsupc++/eh_alloc.cc (EMERGENCY_OBJ_SIZE): Define in units of sizeof(void*) not including the ABI's exception header. (EMERGENCY_OBJ_COUNT): Define as target-independent calculation based on word size. (MAX_OBJ_COUNT): Define macro for upper limit on pool size. (pool) [_GLIBCXX_EH_POOL_STATIC]: Use fixed-size buffer. (pool::buffer_size_in_bytes): New static member function. (pool::pool): Parse GLIBCXX_TUNABLES environment variable to set pool size at runtime. (pool::in_pool): Use std::less for total order. (__freeres) [_GLIBCXX_EH_POOL_STATIC]: Do nothing. (__cxa_free_exception, __cxa_free_dependent_exception): Add [[unlikely]] attributes. * po/Makefile.in: Regenerate. * python/Makefile.in: Regenerate. * src/Makefile.in: Regenerate. * src/c++11/Makefile.in: Regenerate. * src/c++17/Makefile.in: Regenerate. * src/c++20/Makefile.in: Regenerate. * src/c++98/Makefile.in: Regenerate. * src/filesystem/Makefile.in: Regenerate. * src/libbacktrace/Makefile.in: Regenerate. * testsuite/Makefile.in: Regenerate. --- libstdc++-v3/Makefile.in | 1 + libstdc++-v3/acinclude.m4 | 45 ++++ libstdc++-v3/configure | 67 +++++- libstdc++-v3/configure.ac | 3 + libstdc++-v3/crossconfig.m4 | 1 + libstdc++-v3/doc/Makefile.in | 1 + libstdc++-v3/doc/html/index.html | 4 +- libstdc++-v3/doc/html/manual/api.html | 3 + libstdc++-v3/doc/html/manual/appendix.html | 2 +- .../doc/html/manual/appendix_porting.html | 2 +- libstdc++-v3/doc/html/manual/configure.html | 10 +- libstdc++-v3/doc/html/manual/index.html | 4 +- libstdc++-v3/doc/html/manual/intro.html | 2 +- libstdc++-v3/doc/html/manual/using.html | 2 +- .../doc/html/manual/using_exceptions.html | 77 +++++- libstdc++-v3/doc/xml/manual/configure.xml | 23 ++ libstdc++-v3/doc/xml/manual/evolution.xml | 9 + .../doc/xml/manual/using_exceptions.xml | 90 +++++++ libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/libsupc++/Makefile.am | 2 +- libstdc++-v3/libsupc++/Makefile.in | 3 +- libstdc++-v3/libsupc++/eh_alloc.cc | 225 +++++++++++++----- libstdc++-v3/po/Makefile.in | 1 + libstdc++-v3/python/Makefile.in | 1 + libstdc++-v3/src/Makefile.in | 1 + libstdc++-v3/src/c++11/Makefile.in | 1 + libstdc++-v3/src/c++17/Makefile.in | 1 + libstdc++-v3/src/c++20/Makefile.in | 1 + libstdc++-v3/src/c++98/Makefile.in | 1 + libstdc++-v3/src/filesystem/Makefile.in | 1 + libstdc++-v3/src/libbacktrace/Makefile.in | 1 + libstdc++-v3/testsuite/Makefile.in | 1 + 32 files changed, 494 insertions(+), 93 deletions(-) diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in index 58a0acdcc1b..a7c2b60678b 100644 --- a/libstdc++-v3/Makefile.in +++ b/libstdc++-v3/Makefile.in @@ -240,6 +240,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 719eab15c77..6523ba9a816 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -5092,6 +5092,51 @@ BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DBACKTRACE_ELF_SIZE=$elfsize" GLIBCXX_CONDITIONAL(ENABLE_BACKTRACE, [test "$enable_libstdcxx_backtrace" = yes]) ]) +dnl +dnl Allow the emergency EH pool to be configured. +dnl +dnl --enable-libstdcxx-static-eh-pool will cause a fixed-size static buffer +dnl to be used for allocating exceptions after malloc fails. The default is +dnl to allocate a buffer using malloc +dnl +dnl --with-libstdcxx-eh-pool-obj-count=N will set the default size for the +dnl buffer. For a static buffer that size is fixed permanently. For a dynamic +dnl buffer it's the default, but it can be overridden from the environment. +dnl +dnl To set the default to approximately the same values as GCC 12, +dnl use --with-libstdcxx-eh-pool-obj-count=94 for 32-bit targets, +dnl and --with-libstdcxx-eh-pool-obj-count=252 for 64-bit targets. +dnl +dnl Defines: +dnl _GLIBCXX_EH_POOL_STATIC if a fixed-size static buffer should be used +dnl instead of allocating a buffer on startup. +dnl _GLIBCXX_EH_POOL_NOBJS to override the default EMERGENCY_OBJ_COUNT value. +dnl +AC_DEFUN([GLIBCXX_EMERGENCY_EH_ALLOC], [ + eh_pool_static= + eh_pool_nobjs= + AC_ARG_ENABLE([libstdcxx-static-eh-pool], + AC_HELP_STRING([--enable-libstdcxx-static-eh-pool], + [use a fixed-size static buffer for allocating exceptions if malloc fails]), + [if test "${enableval}" = yes; then + eh_pool_static="-D_GLIBCXX_EH_POOL_STATIC" + AC_MSG_NOTICE([EH pool using static buffer]) + fi],) + + AC_ARG_WITH([libstdcxx-eh-pool-obj-count], + AC_HELP_STRING([--with-libstdcxx-eh-pool-obj-count], + [the number of exceptions that can be allocated from the pool if malloc fails]), + [if test "${withval}" -ge 0 2>/dev/null; then + eh_pool_obj_count="-D_GLIBCXX_EH_POOL_NOBJS=${withval}" + AC_MSG_NOTICE([EH pool object count: ${withval}]) + else + AC_MSG_ERROR([EH pool obj count must be a non-negative integer: $withval]) + fi],) + + EH_POOL_FLAGS="$eh_pool_static $eh_pool_obj_count" + AC_SUBST(EH_POOL_FLAGS) +]) + # Macros from the top-level gcc directory. m4_include([../config/gc++filt.m4]) m4_include([../config/tls.m4]) diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 4bb1d73f0e0..b564175a040 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -675,6 +675,7 @@ DOT DOXYGEN BUILD_INFO_FALSE BUILD_INFO_TRUE +EH_POOL_FLAGS ENABLE_BACKTRACE_FALSE ENABLE_BACKTRACE_TRUE BACKTRACE_SUPPORTS_THREADS @@ -958,6 +959,8 @@ with_default_libstdcxx_abi enable_libstdcxx_threads enable_libstdcxx_filesystem_ts enable_libstdcxx_backtrace +enable_libstdcxx_static_eh_pool +with_libstdcxx_eh_pool_obj_count enable_cet with_gxx_include_dir enable_version_specific_runtime_libs @@ -1668,6 +1671,9 @@ Optional Features: turns on ISO/IEC TS 18822 support [default=auto] --enable-libstdcxx-backtrace turns on libbacktrace support [default=auto] + --enable-libstdcxx-static-eh-pool + use a fixed-size static buffer for allocating + exceptions if malloc fails --enable-cet enable Intel CET in target libraries [default=auto] --enable-version-specific-runtime-libs Specify that runtime libraries should be installed @@ -1695,6 +1701,9 @@ Optional Packages: --with-system-libunwind use installed libunwind --with-default-libstdcxx-abi set the std::string ABI to use by default + --with-libstdcxx-eh-pool-obj-count + the number of exceptions that can be allocated from + the pool if malloc fails --with-gxx-include-dir=DIR installation directory for include files --with-toolexeclibdir=DIR @@ -12227,7 +12236,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12206 "configure" +#line 12215 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12333,7 +12342,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12312 "configure" +#line 12321 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16053,7 +16062,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 16012 "configure" +#line 16021 "configure" int main() { typedef bool atomic_type; @@ -16088,7 +16097,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16047 "configure" +#line 16056 "configure" int main() { typedef short atomic_type; @@ -16123,7 +16132,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16082 "configure" +#line 16091 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -16159,7 +16168,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16118 "configure" +#line 16127 "configure" int main() { typedef long long atomic_type; @@ -16315,7 +16324,7 @@ $as_echo "mutex" >&6; } # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16274 "configure" +#line 16283 "configure" int main() { _Decimal32 d1; @@ -16357,7 +16366,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16316 "configure" +#line 16325 "configure" template struct same { typedef T2 type; }; @@ -54268,6 +54277,17 @@ _ACEOF fi done + for ac_func in secure_getenv +do : + ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv" +if test "x$ac_cv_func_secure_getenv" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SECURE_GETENV 1 +_ACEOF + +fi +done + @@ -71916,6 +71936,37 @@ $as_echo "7.1.0" >&6; } fi +# For libsupc++/eh_alloc.cc defaults. + + eh_pool_static= + eh_pool_nobjs= + # Check whether --enable-libstdcxx-static-eh-pool was given. +if test "${enable_libstdcxx_static_eh_pool+set}" = set; then : + enableval=$enable_libstdcxx_static_eh_pool; if test "${enableval}" = yes; then + eh_pool_static="-D_GLIBCXX_EH_POOL_STATIC" + { $as_echo "$as_me:${as_lineno-$LINENO}: EH pool using static buffer" >&5 +$as_echo "$as_me: EH pool using static buffer" >&6;} + fi +fi + + + +# Check whether --with-libstdcxx-eh-pool-obj-count was given. +if test "${with_libstdcxx_eh_pool_obj_count+set}" = set; then : + withval=$with_libstdcxx_eh_pool_obj_count; if test "${withval}" -ge 0 2>/dev/null; then + eh_pool_obj_count="-D_GLIBCXX_EH_POOL_NOBJS=${withval}" + { $as_echo "$as_me:${as_lineno-$LINENO}: EH pool object count: ${withval}" >&5 +$as_echo "$as_me: EH pool object count: ${withval}" >&6;} + else + as_fn_error $? "EH pool obj count must be a non-negative integer: $withval" "$LINENO" 5 + fi +fi + + + EH_POOL_FLAGS="$eh_pool_static $eh_pool_obj_count" + + + # Define documentation rules conditionally. # See if makeinfo has been installed and is modern enough diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index c05fcdda7e9..42c453099f2 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -538,6 +538,9 @@ GLIBCXX_CHECK_SIZE_T_MANGLING # Check which release added std::exception_ptr for the target GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER +# For libsupc++/eh_alloc.cc defaults. +GLIBCXX_EMERGENCY_EH_ALLOC + # Define documentation rules conditionally. # See if makeinfo has been installed and is modern enough diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4 index 130f47fb1d4..b3269cb88e0 100644 --- a/libstdc++-v3/crossconfig.m4 +++ b/libstdc++-v3/crossconfig.m4 @@ -187,6 +187,7 @@ case "${host}" in AC_CHECK_FUNCS(timespec_get) AC_CHECK_FUNCS(sockatmark) AC_CHECK_FUNCS(uselocale) + AC_CHECK_FUNCS(secure_getenv) AM_ICONV ;; *-mingw32*) diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in index 6aaceea7491..469a6082c88 100644 --- a/libstdc++-v3/doc/Makefile.in +++ b/libstdc++-v3/doc/Makefile.in @@ -199,6 +199,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/doc/html/index.html b/libstdc++-v3/doc/html/index.html index 1e0cecbcc4f..ce951e6cc8e 100644 --- a/libstdc++-v3/doc/html/index.html +++ b/libstdc++-v3/doc/html/index.html @@ -23,7 +23,7 @@


Table of Contents

The GNU C++ Library Manual
I. Introduction -
1. Status
Implementation Status
C++ 1998/2003
Implementation Status
Implementation Specific Behavior
C++ 2011
Implementation Specific Behavior
C++ 2014
Implementation Specific Behavior
Filesystem TS
C++ 2017
Implementation Specific Behavior
Parallelism 2 TS
C++ 2020
C++ 2023
C++ TR1
Implementation Specific Behavior
C++ TR 24733
C++ IS 29124
Implementation Specific Behavior
License
The Code: GPL
The Documentation: GPL, FDL
Bugs
Implementation Bugs
Standard Bugs
2. Setup
Prerequisites
Configure
Make
3. Using
Command Options
Headers
Header Files
Mixing Headers
The C Headers and namespace std
Precompiled Headers
Macros
Dual ABI
Troubleshooting
Namespaces
Available Namespaces
namespace std
Using Namespace Composition
Linking
Almost Nothing
Finding Dynamic or Shared Libraries
Experimental Library Extensions
Concurrency
Prerequisites
Thread Safety
Atomics
IO
Structure
Defaults
Future
Alternatives
Containers
Exceptions
Exception Safety
Exception Neutrality
Doing without
Compatibility
With C
With POSIX thread cancellation
Debugging Support
Using g++
Debug Versions of Library Binary Files
Memory Leak Hunting
Non-memory leaks in Pool and MT allocators
Data Race Hunting
Using gdb
Tracking uncaught exceptions
Debug Mode
Compile Time Checking
II. +
1. Status
Implementation Status
C++ 1998/2003
Implementation Status
Implementation Specific Behavior
C++ 2011
Implementation Specific Behavior
C++ 2014
Implementation Specific Behavior
Filesystem TS
C++ 2017
Implementation Specific Behavior
Parallelism 2 TS
C++ 2020
C++ 2023
C++ TR1
Implementation Specific Behavior
C++ TR 24733
C++ IS 29124
Implementation Specific Behavior
License
The Code: GPL
The Documentation: GPL, FDL
Bugs
Implementation Bugs
Standard Bugs
2. Setup
Prerequisites
Configure
Make
3. Using
Command Options
Headers
Header Files
Mixing Headers
The C Headers and namespace std
Precompiled Headers
Macros
Dual ABI
Troubleshooting
Namespaces
Available Namespaces
namespace std
Using Namespace Composition
Linking
Almost Nothing
Finding Dynamic or Shared Libraries
Experimental Library Extensions
Concurrency
Prerequisites
Thread Safety
Atomics
IO
Structure
Defaults
Future
Alternatives
Containers
Exceptions
Exception Safety
Exception Neutrality
Memory allocation
Doing without
Compatibility
With C
With POSIX thread cancellation
Debugging Support
Using g++
Debug Versions of Library Binary Files
Memory Leak Hunting
Non-memory leaks in Pool and MT allocators
Data Race Hunting
Using gdb
Tracking uncaught exceptions
Debug Mode
Compile Time Checking
II. Standard Contents
4. Support @@ -142,7 +142,7 @@ Existing tests
C++11 Requirements Test Sequence Descriptions -
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace. +
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
13
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace.
No stream::attach(int fd)
diff --git a/libstdc++-v3/doc/html/manual/api.html b/libstdc++-v3/doc/html/manual/api.html index 604380e0136..d9857675c78 100644 --- a/libstdc++-v3/doc/html/manual/api.html +++ b/libstdc++-v3/doc/html/manual/api.html @@ -473,4 +473,7 @@ the process.

12.3

Calling a std::bind result as volatile is ill-formed for C++20 and later. +

13

+Tunables <variable>glibcxx.eh_pool.obj_count</variable> and +<variable>glibcxx.eh_pool.obj_size</variable> were added.

\ No newline at end of file diff --git a/libstdc++-v3/doc/html/manual/appendix.html b/libstdc++-v3/doc/html/manual/appendix.html index c563372e441..3f8bac01587 100644 --- a/libstdc++-v3/doc/html/manual/appendix.html +++ b/libstdc++-v3/doc/html/manual/appendix.html @@ -16,7 +16,7 @@ Existing tests
C++11 Requirements Test Sequence Descriptions -
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace. +
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
13
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace.
No stream::attach(int fd)
diff --git a/libstdc++-v3/doc/html/manual/appendix_porting.html b/libstdc++-v3/doc/html/manual/appendix_porting.html index 55d3f2318dd..4b3f0698803 100644 --- a/libstdc++-v3/doc/html/manual/appendix_porting.html +++ b/libstdc++-v3/doc/html/manual/appendix_porting.html @@ -14,7 +14,7 @@ Existing tests
C++11 Requirements Test Sequence Descriptions -
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace. +
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
13
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace.
No stream::attach(int fd)
diff --git a/libstdc++-v3/doc/html/manual/configure.html b/libstdc++-v3/doc/html/manual/configure.html index 31c4da8a5e3..66adc7d77b1 100644 --- a/libstdc++-v3/doc/html/manual/configure.html +++ b/libstdc++-v3/doc/html/manual/configure.html @@ -220,7 +220,7 @@ freestanding environment, in which only a minimal set of headers are provided. This option builds such an environment. -

--disable-libstdcxx-verbose

+

--disable-libstdcxx-hosted

This is an alias for --disable-hosted-libstdcxx.

--disable-libstdcxx-verbose

By default, the library is configured to write descriptive messages to standard error for certain events such as calling a pure virtual function or the invocation of the standard terminate handler. Those @@ -271,4 +271,12 @@ as the usual libstdc++ and libsupc++ libraries. This is enabled by default on select POSIX targets where it is known to work and disabled otherwise. +

--enable-libstdcxx-static-eh-pool

Use a fixed-size static buffer for the emergency exception handling + pool (see Memory allocation for exceptions). The default + is to allocate the pool on program startup using malloc. + With this option, a static buffer will be provided by libstdc++ instead. + This does not change the library ABI. +

--with-libstdcxx-eh-pool-obj-count=NUM

Set the size of the emergency exception handling pool. NUM is the + number of simultaneous allocated exceptions to support. + This does not change the library ABI.

\ No newline at end of file diff --git a/libstdc++-v3/doc/html/manual/index.html b/libstdc++-v3/doc/html/manual/index.html index 2949509bca3..292afde6051 100644 --- a/libstdc++-v3/doc/html/manual/index.html +++ b/libstdc++-v3/doc/html/manual/index.html @@ -4,7 +4,7 @@


Table of Contents

I. Introduction -
1. Status
Implementation Status
C++ 1998/2003
Implementation Status
Implementation Specific Behavior
C++ 2011
Implementation Specific Behavior
C++ 2014
Implementation Specific Behavior
Filesystem TS
C++ 2017
Implementation Specific Behavior
Parallelism 2 TS
C++ 2020
C++ 2023
C++ TR1
Implementation Specific Behavior
C++ TR 24733
C++ IS 29124
Implementation Specific Behavior
License
The Code: GPL
The Documentation: GPL, FDL
Bugs
Implementation Bugs
Standard Bugs
2. Setup
Prerequisites
Configure
Make
3. Using
Command Options
Headers
Header Files
Mixing Headers
The C Headers and namespace std
Precompiled Headers
Macros
Dual ABI
Troubleshooting
Namespaces
Available Namespaces
namespace std
Using Namespace Composition
Linking
Almost Nothing
Finding Dynamic or Shared Libraries
Experimental Library Extensions
Concurrency
Prerequisites
Thread Safety
Atomics
IO
Structure
Defaults
Future
Alternatives
Containers
Exceptions
Exception Safety
Exception Neutrality
Doing without
Compatibility
With C
With POSIX thread cancellation
Debugging Support
Using g++
Debug Versions of Library Binary Files
Memory Leak Hunting
Non-memory leaks in Pool and MT allocators
Data Race Hunting
Using gdb
Tracking uncaught exceptions
Debug Mode
Compile Time Checking
II. +
1. Status
Implementation Status
C++ 1998/2003
Implementation Status
Implementation Specific Behavior
C++ 2011
Implementation Specific Behavior
C++ 2014
Implementation Specific Behavior
Filesystem TS
C++ 2017
Implementation Specific Behavior
Parallelism 2 TS
C++ 2020
C++ 2023
C++ TR1
Implementation Specific Behavior
C++ TR 24733
C++ IS 29124
Implementation Specific Behavior
License
The Code: GPL
The Documentation: GPL, FDL
Bugs
Implementation Bugs
Standard Bugs
2. Setup
Prerequisites
Configure
Make
3. Using
Command Options
Headers
Header Files
Mixing Headers
The C Headers and namespace std
Precompiled Headers
Macros
Dual ABI
Troubleshooting
Namespaces
Available Namespaces
namespace std
Using Namespace Composition
Linking
Almost Nothing
Finding Dynamic or Shared Libraries
Experimental Library Extensions
Concurrency
Prerequisites
Thread Safety
Atomics
IO
Structure
Defaults
Future
Alternatives
Containers
Exceptions
Exception Safety
Exception Neutrality
Memory allocation
Doing without
Compatibility
With C
With POSIX thread cancellation
Debugging Support
Using g++
Debug Versions of Library Binary Files
Memory Leak Hunting
Non-memory leaks in Pool and MT allocators
Data Race Hunting
Using gdb
Tracking uncaught exceptions
Debug Mode
Compile Time Checking
II. Standard Contents
4. Support @@ -123,7 +123,7 @@ Existing tests
C++11 Requirements Test Sequence Descriptions -
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace. +
ABI Policy and Guidelines
The C++ Interface
Versioning
Goals
History
Prerequisites
Configuring
Checking Active
Allowed Changes
Prohibited Changes
Implementation
Testing
Single ABI Testing
Multiple ABI Testing
Outstanding Issues
API Evolution and Deprecation History
3.0
3.1
3.2
3.3
3.4
4.0
4.1
4.2
4.3
4.4
4.5
4.6
4.7
4.8
4.9
5
5.3
6
7
7.2
7.3
8
9
10
11
12
12.3
13
Backwards Compatibility
First
Second
Third
Pre-ISO headers removed
Extension headers hash_map, hash_set moved to ext or backwards
No ios::nocreate/ios::noreplace.
No stream::attach(int fd)
diff --git a/libstdc++-v3/doc/html/manual/intro.html b/libstdc++-v3/doc/html/manual/intro.html index 1a8234437d9..3027cb6f3f7 100644 --- a/libstdc++-v3/doc/html/manual/intro.html +++ b/libstdc++-v3/doc/html/manual/intro.html @@ -5,4 +5,4 @@ Prev The GNU C++ Library Manual Next
\ No newline at end of file + \ No newline at end of file diff --git a/libstdc++-v3/doc/html/manual/using.html b/libstdc++-v3/doc/html/manual/using.html index 08facffa445..f2dc2078759 100644 --- a/libstdc++-v3/doc/html/manual/using.html +++ b/libstdc++-v3/doc/html/manual/using.html @@ -2,7 +2,7 @@ Chapter 3. Using

Chapter 3. Using

Command Options

Next


Chapter 3. Using

Command Options

The set of features available in the GNU C++ library is shaped by several GCC Command Options. Options that impact libstdc++ are diff --git a/libstdc++-v3/doc/html/manual/using_exceptions.html b/libstdc++-v3/doc/html/manual/using_exceptions.html index 3ae0beaf2c6..88bc05dab99 100644 --- a/libstdc++-v3/doc/html/manual/using_exceptions.html +++ b/libstdc++-v3/doc/html/manual/using_exceptions.html @@ -100,7 +100,62 @@ exception neutrality and exception safety. The constructors of thread that take a callable function argument swallow all exceptions resulting from executing the function argument. -

Doing without

+

Memory allocation

+ When the program throws an exception the runtime will obtain storage for + a __cxa_exception header and the thrown object itself. + Libstdc++ will try to use malloc to obtain storage, + but provides an emergency buffer to be used if malloc fails, + as described by the Itanium + exception handling ABI. +

+ Contrary to the ABI, the libstdc++ emergency buffer is not always 64kB, + and does not always allocate 1kB chunks. The buffer is used as a pool for + variable-sized allocations, so that it doesn't waste space for smaller + exception objects such as std::bad_alloc. + The total size of the buffer is scaled appropriately for the target. + Specifically it depends on sizeof(void*), so that a 64-bit + system uses a larger pool than a 32-bit system. This is done because for + 32-bit systems the exception objects (and the exception header) require + less space, and core counts and thread counts are typically lower as well. +

+ By default, libstdc++ will use malloc to allocate the buffer + on program startup. + Configuring libstdc++ with the + --enable-libstdcxx-static-eh-pool option will make it + use a static buffer instead of using malloc. +

+ The buffer size is chosen automatically, but can be overridden + by configuring with --with-libstdcxx-eh-pool-obj-count=NUM, + where NUM is the number of simultaneous allocations that + should be supported. The size of the pool will be sufficient for + NUM exceptions of 6 * sizeof(void*) bytes, + plus another NUM exceptions captured in + std::exception_ptr and rethrown using + std::rethrow_exception. The buffer size determined by the + obj-count value applies whether the buffer is reserved as static storage + or is allocated dynamically. + Setting obj-count to zero will disable the pool, so that no emergency + buffer is present. +

+ For a dynamic buffer, the default size can also be changed at runtime, + per-process, via the GLIBCXX_TUNABLES environment + variable. + The GLIBCXX_TUNABLES environment variable should be + a string of colon-separated name=value pairs. The + following names will be recognized, with the specified semantics: +

glibcxx.eh_pool.obj_count
+ The number of exception objects to provide space for in the pool. + The value must be a non-negative integer and has the same meaning as the + --with-libstdcxx-eh-pool-obj-count option for + configure. +
glibcxx.eh_pool.obj_size
+ The expected size of exception objects that the pool might get used for. + The value must be a positive integer, and is measured in units of + sizeof(void*). The default value is 6 + which is large enough to store any exception type thrown by libstdc++. + Exceptions larger than this can still be allocated from the pool, + but larger exceptions will exhaust the pool more rapidly. +

Doing without

C++ is a language that strives to be as efficient as is possible in delivering features. As such, considerable care is used by both language implementer and designers to make sure unused features @@ -265,7 +320,7 @@ is called. } catch(...) { this->_M_setstate(ios_base::badbit); } -

Bibliography

+

Bibliography

System Interface Definitions, Issue 7 (IEEE Std. 1003.1-2008) @@ -274,40 +329,44 @@ is called. . Copyright © 2008 The Open Group/The Institute of Electrical and Electronics Engineers, Inc. - .

+ .

Error and Exception Handling . David Abrahams . Boost - .

+ .

Exception-Safety in Generic Components . David Abrahams. Boost - .

+ .

Standard Library Exception Policy . Matt Austern. WG21 N1077 - .

+ .

ia64 c++ abi exception handling . Richard Henderson. GNU - .

+ .

+ . Bjarne Stroustrup.

Exceptional C++ . Exception-Safety Issues and Techniques - . Herb Sutter.

+ . Herb Sutter.

\ No newline at end of file diff --git a/libstdc++-v3/doc/xml/manual/configure.xml b/libstdc++-v3/doc/xml/manual/configure.xml index 8c26acc95a7..c6c5981968d 100644 --- a/libstdc++-v3/doc/xml/manual/configure.xml +++ b/libstdc++-v3/doc/xml/manual/configure.xml @@ -366,6 +366,11 @@ + --disable-libstdcxx-hosted + + This is an alias for --disable-hosted-libstdcxx. + + --disable-libstdcxx-verbose @@ -446,6 +451,24 @@ + --enable-libstdcxx-static-eh-pool + + Use a fixed-size static buffer for the emergency exception handling + pool (see ). The default + is to allocate the pool on program startup using malloc. + With this option, a static buffer will be provided by libstdc++ instead. + This does not change the library ABI. + + + + --with-libstdcxx-eh-pool-obj-count=NUM + + Set the size of the emergency exception handling pool. NUM is the + number of simultaneous allocated exceptions to support. + This does not change the library ABI. + + + diff --git a/libstdc++-v3/doc/xml/manual/evolution.xml b/libstdc++-v3/doc/xml/manual/evolution.xml index 82936189179..a29e4df3822 100644 --- a/libstdc++-v3/doc/xml/manual/evolution.xml +++ b/libstdc++-v3/doc/xml/manual/evolution.xml @@ -1080,4 +1080,13 @@ and later. +
<constant>13</constant> + + +Tunables glibcxx.eh_pool.obj_count and +glibcxx.eh_pool.obj_size were added. + + +
+ diff --git a/libstdc++-v3/doc/xml/manual/using_exceptions.xml b/libstdc++-v3/doc/xml/manual/using_exceptions.xml index 32bff85549f..47dedc14c73 100644 --- a/libstdc++-v3/doc/xml/manual/using_exceptions.xml +++ b/libstdc++-v3/doc/xml/manual/using_exceptions.xml @@ -188,6 +188,87 @@ exception neutrality and exception safety. +
Memory allocation + + + When the program throws an exception the runtime will obtain storage for + a __cxa_exception header and the thrown object itself. + Libstdc++ will try to use malloc to obtain storage, + but provides an emergency buffer to be used if malloc fails, + as described by the Itanium + exception handling ABI. + + + + Contrary to the ABI, the libstdc++ emergency buffer is not always 64kB, + and does not always allocate 1kB chunks. The buffer is used as a pool for + variable-sized allocations, so that it doesn't waste space for smaller + exception objects such as std::bad_alloc. + The total size of the buffer is scaled appropriately for the target. + Specifically it depends on sizeof(void*), so that a 64-bit + system uses a larger pool than a 32-bit system. This is done because for + 32-bit systems the exception objects (and the exception header) require + less space, and core counts and thread counts are typically lower as well. + + + + By default, libstdc++ will use malloc to allocate the buffer + on program startup. + libstdc++ with the + --enable-libstdcxx-static-eh-pool option will make it + use a static buffer instead of using malloc. + + + + The buffer size is chosen automatically, but can be overridden + by configuring with --with-libstdcxx-eh-pool-obj-count=NUM, + where NUM is the number of simultaneous allocations that + should be supported. The size of the pool will be sufficient for + NUM exceptions of 6 * sizeof(void*) bytes, + plus another NUM exceptions captured in + std::exception_ptr and rethrown using + std::rethrow_exception. The buffer size determined by the + obj-count value applies whether the buffer is reserved as static storage + or is allocated dynamically. + Setting obj-count to zero will disable the pool, so that no emergency + buffer is present. + + + + For a dynamic buffer, the default size can also be changed at runtime, + per-process, via the GLIBCXX_TUNABLES environment + variable. + The GLIBCXX_TUNABLES environment variable should be + a string of colon-separated name=value pairs. The + following names will be recognized, with the specified semantics: + + + + + glibcxx.eh_pool.obj_count + + The number of exception objects to provide space for in the pool. + The value must be a non-negative integer and has the same meaning as the + --with-libstdcxx-eh-pool-obj-count option for + configure. + + + + glibcxx.eh_pool.obj_size + + The expected size of exception objects that the pool might get used for. + The value must be a positive integer, and is measured in units of + sizeof(void*). The default value is 6 + which is large enough to store any exception type thrown by libstdc++. + Exceptions larger than this can still be allocated from the pool, + but larger exceptions will exhaust the pool more rapidly. + + + + +
+
Doing without @@ -538,6 +619,15 @@ is called. + + + <link xmlns:xlink="http://www.w3.org/1999/xlink" + xlink:href="https://www.gnu.org/software/libc/manual/html_node/Tunables.html"> + Tunables, The GNU C Library + </link> + + +
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 9d6075511f7..0a3a1e34491 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -199,6 +199,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 65b5c1a87fd..cde9fbdb1eb 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -139,7 +139,7 @@ atomicity.cc: ${atomicity_file} # as the occasion call for it. AM_CXXFLAGS = \ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ - $(XTEMPLATE_FLAGS) $(FREESTANDING_FLAGS) \ + $(XTEMPLATE_FLAGS) $(FREESTANDING_FLAGS) $(EH_POOL_FLAGS) \ $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) AM_MAKEFLAGS = \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index a4402009b85..1127095493c 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -308,6 +308,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ @@ -587,7 +588,7 @@ atomicity_file = ${glibcxx_srcdir}/$(ATOMICITY_SRCDIR)/atomicity.h # as the occasion call for it. AM_CXXFLAGS = \ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ - $(XTEMPLATE_FLAGS) $(FREESTANDING_FLAGS) \ + $(XTEMPLATE_FLAGS) $(FREESTANDING_FLAGS) $(EH_POOL_FLAGS) \ $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) AM_MAKEFLAGS = \ diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc index 68f319869f9..50dc37c0d9c 100644 --- a/libstdc++-v3/libsupc++/eh_alloc.cc +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -25,16 +25,45 @@ // This is derived from the C++ ABI for IA-64. Where we diverge // for cross-architecture compatibility are noted with "@@@". -#include -#include -#if _GLIBCXX_HOSTED -#include -#endif -#include -#include +#include // std::exception +#include // std::terminate +#include // std::malloc, std::free, std::strtoul +#include // INT_MAX +#include // std::less #include "unwind-cxx.h" -#include -#include +#if _GLIBCXX_HOSTED +# include // std::string_view +# include // std::strchr, std::memset +# include // __gnu_cxx::__mutex, __gnu_cxx::__scoped_lock +#endif + +// We use an emergency buffer used for exceptions when malloc fails. +// If _GLIBCXX_EH_POOL_STATIC is defined (e.g. by configure) then we use +// a fixed-size static buffer. Otherwise, allocate on startup using malloc. +// +// The size of the buffer is N * (S * P + R + D), where: +// N == The number of objects to reserve space for. +// Defaults to EMERGENCY_OBJ_COUNT, defined below. +// S == Estimated size of exception objects to account for. +// This size is in units of sizeof(void*) not bytes. +// Defaults to EMERGENCY_OBJ_SIZE, defined below. +// P == sizeof(void*). +// R == sizeof(__cxa_refcounted_exception). +// D == sizeof(__cxa_dependent_exception). +// +// This provides space for N thrown exceptions of S words each, and an +// additional N dependent exceptions from std::rethrow_exception. +// +// The calculation allows values of N and S to be target-independent, +// as the size will be scaled by the size of basic types on the target, +// and space for the C++ exception header (__cxa_refcounted_exception) +// is added automatically. +// +// For a dynamically allocated buffer, N and S can be set from the environment. +// Setting N=0 will disable the emergency buffer. +// The GLIBCXX_TUNABLES environment variable will be checked for the following: +// - Tunable glibcxx.eh_pool.obj_count overrides EMERGENCY_OBJ_COUNT. +// - Tunable glibcxx.eh_pool.obj_size overrides EMERGENCY_OBJ_SIZE. #if _GLIBCXX_HOSTED using std::free; @@ -50,46 +79,61 @@ extern "C" void *memset (void *, int, std::size_t); using namespace __cxxabiv1; -// ??? How to control these parameters. +// Assume that 6 * sizeof(void*) is a reasonable exception object size. +// Throwing very many large objects will exhaust the pool more quickly. +// N.B. sizeof(std::bad_alloc) == sizeof(void*) +// and sizeof(std::runtime_error) == 2 * sizeof(void*) +// and sizeof(std::system_error) == 4 * sizeof(void*). +#define EMERGENCY_OBJ_SIZE 6 -// Guess from the size of basic types how large a buffer is reasonable. -// Note that the basic c++ exception header has 13 pointers and 2 ints, -// so on a system with PSImode pointers we're talking about 56 bytes -// just for overhead. - -#if INT_MAX == 32767 -# define EMERGENCY_OBJ_SIZE 128 -# define EMERGENCY_OBJ_COUNT 16 -#elif !defined (_GLIBCXX_LLP64) && LONG_MAX == 2147483647 -# define EMERGENCY_OBJ_SIZE 512 -# define EMERGENCY_OBJ_COUNT 32 +#ifdef __GTHREADS +// Assume that the number of concurrent exception objects scales with the +// processor word size, i.e., 16-bit systems are not likely to have hundreds +// of threads all simultaneously throwing on OOM conditions. +# define EMERGENCY_OBJ_COUNT (4 * __SIZEOF_POINTER__ * __SIZEOF_POINTER__) +# define MAX_OBJ_COUNT (16 << __SIZEOF_POINTER__) #else -# define EMERGENCY_OBJ_SIZE 1024 -# define EMERGENCY_OBJ_COUNT 64 +# define EMERGENCY_OBJ_COUNT 4 +# define MAX_OBJ_COUNT 64 #endif -#ifndef __GTHREADS -# undef EMERGENCY_OBJ_COUNT -# define EMERGENCY_OBJ_COUNT 4 +// This can be set by configure. +#ifdef _GLIBCXX_EH_POOL_NOBJS +# if _GLIBCXX_EH_POOL_NOBJS > MAX_OBJ_COUNT +# warning "_GLIBCXX_EH_POOL_NOBJS value is too large; ignoring it" +# else +# undef EMERGENCY_OBJ_COUNT +# define EMERGENCY_OBJ_COUNT _GLIBCXX_EH_POOL_NOBJS +# endif #endif namespace __gnu_cxx { - void __freeres(); + void __freeres() noexcept; } namespace { + static constexpr std::size_t + buffer_size_in_bytes(std::size_t obj_count, std::size_t obj_size) noexcept + { + // N * (S * P + R + D) + constexpr std::size_t P = sizeof(void*); + constexpr std::size_t R = sizeof(__cxa_refcounted_exception); + constexpr std::size_t D = sizeof(__cxa_dependent_exception); + return obj_count * (obj_size * P + R + D); + } + // A fixed-size heap, variable size object allocator class pool { public: - pool(); + pool() noexcept; - _GLIBCXX_NODISCARD void *allocate (std::size_t); - void free (void *); + _GLIBCXX_NODISCARD void *allocate (std::size_t) noexcept; + void free (void *) noexcept; - bool in_pool (void *); + bool in_pool (void *) const noexcept; private: struct free_entry { @@ -101,33 +145,87 @@ namespace char data[] __attribute__((aligned)); }; +#ifdef __GTHREADS // A single mutex controlling emergency allocations. __gnu_cxx::__mutex emergency_mutex; + using __scoped_lock = __gnu_cxx::__scoped_lock; +#else + int emergency_mutex = 0; + struct __scoped_lock { explicit __scoped_lock(int) { } }; +#endif // The free-list - free_entry *first_free_entry; + free_entry *first_free_entry = nullptr; // The arena itself - we need to keep track of these only // to implement in_pool. - char *arena; - std::size_t arena_size; +#ifdef _GLIBCXX_EH_POOL_STATIC + static constexpr std::size_t arena_size + = buffer_size_in_bytes(EMERGENCY_OBJ_COUNT, EMERGENCY_OBJ_SIZE); + alignas(void*) char arena[std::max(arena_size, sizeof(free_entry))]; +#else + char *arena = nullptr; + std::size_t arena_size = 0; +#endif - friend void __gnu_cxx::__freeres(); + friend void __gnu_cxx::__freeres() noexcept; }; - pool::pool() + pool::pool() noexcept { - // Allocate the arena - we could add a GLIBCXX_EH_ARENA_SIZE environment - // to make this tunable. - arena_size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT - + EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception)); +#ifndef _GLIBCXX_EH_POOL_STATIC + int obj_size = EMERGENCY_OBJ_SIZE; + int obj_count = EMERGENCY_OBJ_COUNT; + +#if _GLIBCXX_HOSTED +#if _GLIBCXX_HAVE_SECURE_GETENV + const char* str = ::secure_getenv("GLIBCXX_TUNABLES"); +#else + const char* str = std::getenv("GLIBCXX_TUNABLES"); +#endif + const std::string_view ns_name = "glibcxx.eh_pool"; + std::pair tunables[]{ + {"obj_size", 0}, {"obj_count", obj_count} + }; + while (str) + { + if (*str == ':') + ++str; + + if (!ns_name.compare(0, ns_name.size(), str, ns_name.size()) + && str[ns_name.size()] == '.') + { + str += ns_name.size() + 1; + for (auto& t : tunables) + if (!t.first.compare(0, t.first.size(), str, t.first.size()) + && str[t.first.size()] == '=') + { + str += t.first.size() + 1; + char* end; + unsigned long val = strtoul(str, &end, 0); + if ((*end == ':' || *end == '\0') && val <= INT_MAX) + t.second = val; + str = end; + break; + } + } + str = strchr(str, ':'); + } + obj_count = std::min(tunables[1].second, MAX_OBJ_COUNT); // Can be zero. + if (tunables[0].second != 0) + obj_size = tunables[0].second; +#endif // HOSTED + + arena_size = buffer_size_in_bytes(obj_count, obj_size); + if (arena_size == 0) + return; arena = (char *)malloc (arena_size); if (!arena) { // If the allocation failed go without an emergency pool. arena_size = 0; - first_free_entry = NULL; return; } +#endif // STATIC // Populate the free-list with a single entry covering the whole arena first_free_entry = reinterpret_cast (arena); @@ -136,7 +234,7 @@ namespace first_free_entry->next = NULL; } - void *pool::allocate (std::size_t size) + void *pool::allocate (std::size_t size) noexcept { __gnu_cxx::__scoped_lock sentry(emergency_mutex); // We need an additional size_t member plus the padding to @@ -188,9 +286,9 @@ namespace return &x->data; } - void pool::free (void *data) + void pool::free (void *data) noexcept { - __gnu_cxx::__scoped_lock sentry(emergency_mutex); + __scoped_lock sentry(emergency_mutex); allocated_entry *e = reinterpret_cast (reinterpret_cast (data) - offsetof (allocated_entry, data)); std::size_t sz = e->size; @@ -252,11 +350,10 @@ namespace } } - bool pool::in_pool (void *ptr) + inline bool pool::in_pool (void *ptr) const noexcept { - char *p = reinterpret_cast (ptr); - return (p > arena - && p < arena + arena_size); + std::less less; + return less(ptr, arena + arena_size) && less(arena, ptr); } pool emergency_pool; @@ -264,24 +361,26 @@ namespace namespace __gnu_cxx { + __attribute__((cold)) void - __freeres() + __freeres() noexcept { +#ifndef _GLIBCXX_EH_POOL_STATIC if (emergency_pool.arena) { ::free(emergency_pool.arena); emergency_pool.arena = 0; } +#endif } } extern "C" void * -__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW +__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) noexcept { - void *ret; - thrown_size += sizeof (__cxa_refcounted_exception); - ret = malloc (thrown_size); + + void *ret = malloc (thrown_size); if (!ret) ret = emergency_pool.allocate (thrown_size); @@ -296,10 +395,10 @@ __cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW extern "C" void -__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW +__cxxabiv1::__cxa_free_exception(void *vptr) noexcept { char *ptr = (char *) vptr - sizeof (__cxa_refcounted_exception); - if (emergency_pool.in_pool (ptr)) + if (emergency_pool.in_pool (ptr)) [[__unlikely__]] emergency_pool.free (ptr); else free (ptr); @@ -307,31 +406,27 @@ __cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW extern "C" __cxa_dependent_exception* -__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW +__cxxabiv1::__cxa_allocate_dependent_exception() noexcept { - __cxa_dependent_exception *ret; - - ret = static_cast<__cxa_dependent_exception*> - (malloc (sizeof (__cxa_dependent_exception))); + void *ret = malloc (sizeof (__cxa_dependent_exception)); if (!ret) - ret = static_cast <__cxa_dependent_exception*> - (emergency_pool.allocate (sizeof (__cxa_dependent_exception))); + ret = emergency_pool.allocate (sizeof (__cxa_dependent_exception)); if (!ret) std::terminate (); memset (ret, 0, sizeof (__cxa_dependent_exception)); - return ret; + return static_cast<__cxa_dependent_exception*>(ret); } extern "C" void __cxxabiv1::__cxa_free_dependent_exception - (__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW + (__cxa_dependent_exception *vptr) noexcept { - if (emergency_pool.in_pool (vptr)) + if (emergency_pool.in_pool (vptr)) [[__unlikely__]] emergency_pool.free (vptr); else free (vptr); diff --git a/libstdc++-v3/po/Makefile.in b/libstdc++-v3/po/Makefile.in index 243f3db7b72..af3d4c43d89 100644 --- a/libstdc++-v3/po/Makefile.in +++ b/libstdc++-v3/po/Makefile.in @@ -199,6 +199,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/python/Makefile.in b/libstdc++-v3/python/Makefile.in index 9da4b31fc83..0c600deddb3 100644 --- a/libstdc++-v3/python/Makefile.in +++ b/libstdc++-v3/python/Makefile.in @@ -229,6 +229,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index cef290c5d11..c54c0f63a51 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -301,6 +301,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in index 4db28bd8515..013ab3cb0a7 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -266,6 +266,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/c++17/Makefile.in b/libstdc++-v3/src/c++17/Makefile.in index b88917e101a..217cbbe8321 100644 --- a/libstdc++-v3/src/c++17/Makefile.in +++ b/libstdc++-v3/src/c++17/Makefile.in @@ -245,6 +245,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/c++20/Makefile.in b/libstdc++-v3/src/c++20/Makefile.in index 197d75b8e4b..c04bb7d1ec0 100644 --- a/libstdc++-v3/src/c++20/Makefile.in +++ b/libstdc++-v3/src/c++20/Makefile.in @@ -240,6 +240,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in index 90eff5da986..77ec8c7104f 100644 --- a/libstdc++-v3/src/c++98/Makefile.in +++ b/libstdc++-v3/src/c++98/Makefile.in @@ -261,6 +261,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/filesystem/Makefile.in b/libstdc++-v3/src/filesystem/Makefile.in index 8986b427fba..010bcfc06b7 100644 --- a/libstdc++-v3/src/filesystem/Makefile.in +++ b/libstdc++-v3/src/filesystem/Makefile.in @@ -269,6 +269,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/src/libbacktrace/Makefile.in b/libstdc++-v3/src/libbacktrace/Makefile.in index 5c6b4dd1a0c..a52f645a377 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.in +++ b/libstdc++-v3/src/libbacktrace/Makefile.in @@ -302,6 +302,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in index 17080605676..328a03666c9 100644 --- a/libstdc++-v3/testsuite/Makefile.in +++ b/libstdc++-v3/testsuite/Makefile.in @@ -199,6 +199,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +EH_POOL_FLAGS = @EH_POOL_FLAGS@ ERROR_CONSTANTS_SRCDIR = @ERROR_CONSTANTS_SRCDIR@ EXEEXT = @EXEEXT@ EXTRA_CFLAGS = @EXTRA_CFLAGS@