mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-23 10:54:07 +08:00
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<void*> 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.
This commit is contained in:
parent
576d524559
commit
637e3668fd
@ -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@
|
||||
|
@ -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])
|
||||
|
67
libstdc++-v3/configure
vendored
67
libstdc++-v3/configure
vendored
@ -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<typename T1, typename T2>
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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*)
|
||||
|
@ -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@
|
||||
|
File diff suppressed because one or more lines are too long
@ -473,4 +473,7 @@ the process.
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="api.rel_123"></a><code class="constant">12.3</code></h3></div></div></div><p>
|
||||
Calling a <code class="code">std::bind</code> result as volatile is ill-formed for C++20
|
||||
and later.
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="api.rel_131"></a><code class="constant">13</code></h3></div></div></div><p>
|
||||
Tunables <span style="color: red"><variable>glibcxx.eh_pool.obj_count</variable></span> and
|
||||
<span style="color: red"><variable>glibcxx.eh_pool.obj_size</variable></span> were added.
|
||||
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="abi.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="appendix_porting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="backwards.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">ABI Policy and Guidelines </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Backwards Compatibility</td></tr></table></div></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -220,7 +220,7 @@
|
||||
<span class="emphasis"><em>freestanding</em></span> environment, in which only a
|
||||
minimal set of headers are provided. This option builds such an
|
||||
environment.
|
||||
</p></dd><dt><span class="term"><code class="code">--disable-libstdcxx-verbose</code></span></dt><dd><p>
|
||||
</p></dd><dt><span class="term"><code class="code">--disable-libstdcxx-hosted</code></span></dt><dd><p>This is an alias for <code class="code">--disable-hosted-libstdcxx</code>.</p></dd><dt><span class="term"><code class="code">--disable-libstdcxx-verbose</code></span></dt><dd><p>
|
||||
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.
|
||||
</p></dd><dt><span class="term"><code class="code">--enable-libstdcxx-static-eh-pool</code></span></dt><dd><p>Use a fixed-size static buffer for the emergency exception handling
|
||||
pool (see <a class="xref" href="using_exceptions.html#intro.using.exception.alloc" title="Memory allocation">Memory allocation for exceptions</a>). The default
|
||||
is to allocate the pool on program startup using <code class="code">malloc</code>.
|
||||
With this option, a static buffer will be provided by libstdc++ instead.
|
||||
This does not change the library ABI.
|
||||
</p></dd><dt><span class="term"><code class="code">--with-libstdcxx-eh-pool-obj-count=NUM</code></span></dt><dd><p>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.
|
||||
</p></dd></dl></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="setup.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="setup.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="make.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 2. Setup </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Make</td></tr></table></div></body></html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -100,7 +100,62 @@ exception neutrality and exception safety.
|
||||
The constructors of <code class="classname">thread</code> that take a
|
||||
callable function argument swallow all exceptions resulting from
|
||||
executing the function argument.
|
||||
</p></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="intro.using.exception.no"></a>Doing without</h3></div></div></div><p>
|
||||
</p></li></ul></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="intro.using.exception.alloc"></a>Memory allocation</h3></div></div></div><p>
|
||||
When the program throws an exception the runtime will obtain storage for
|
||||
a <code class="code">__cxa_exception</code> header and the thrown object itself.
|
||||
Libstdc++ will try to use <code class="code">malloc</code> to obtain storage,
|
||||
but provides an emergency buffer to be used if malloc fails,
|
||||
as described by the <a class="link" href="https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#imp-emergency" target="_top">Itanium
|
||||
exception handling ABI</a>.
|
||||
</p><p>
|
||||
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 <code class="code">std::bad_alloc</code>.
|
||||
The total size of the buffer is scaled appropriately for the target.
|
||||
Specifically it depends on <code class="code">sizeof(void*)</code>, 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.
|
||||
</p><p>
|
||||
By default, libstdc++ will use <code class="code">malloc</code> to allocate the buffer
|
||||
on program startup.
|
||||
<a class="xref" href="configure.html" title="Configure">Configuring</a> libstdc++ with the
|
||||
<code class="code">--enable-libstdcxx-static-eh-pool</code> option will make it
|
||||
use a static buffer instead of using <code class="code">malloc</code>.
|
||||
</p><p>
|
||||
The buffer size is chosen automatically, but can be overridden
|
||||
by configuring with <code class="code">--with-libstdcxx-eh-pool-obj-count=NUM</code>,
|
||||
where <code class="code">NUM</code> is the number of simultaneous allocations that
|
||||
should be supported. The size of the pool will be sufficient for
|
||||
<code class="code">NUM</code> exceptions of <code class="code">6 * sizeof(void*)</code> bytes,
|
||||
plus another <code class="code">NUM</code> exceptions captured in
|
||||
<code class="classname">std::exception_ptr</code> and rethrown using
|
||||
<code class="code">std::rethrow_exception</code>. 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.
|
||||
</p><p>
|
||||
For a dynamic buffer, the default size can also be changed at runtime,
|
||||
per-process, via the <code class="literal">GLIBCXX_TUNABLES</code> environment
|
||||
variable.
|
||||
The <code class="literal">GLIBCXX_TUNABLES</code> environment variable should be
|
||||
a string of colon-separated <span class="emphasis"><em>name=value</em></span> pairs. The
|
||||
following names will be recognized, with the specified semantics:
|
||||
</p><div class="variablelist"><dl class="variablelist"><dt><span class="term"><code class="code">glibcxx.eh_pool.obj_count</code></span></dt><dd>
|
||||
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
|
||||
<code class="code">--with-libstdcxx-eh-pool-obj-count</code> option for
|
||||
<code class="filename">configure</code>.
|
||||
</dd><dt><span class="term"><code class="code">glibcxx.eh_pool.obj_size</code></span></dt><dd>
|
||||
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
|
||||
<code class="code">sizeof(void*)</code>. The default value is <code class="literal">6</code>
|
||||
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.
|
||||
</dd></dl></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="intro.using.exception.no"></a>Doing without</h3></div></div></div><p>
|
||||
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); }
|
||||
</pre></div></div><div class="bibliography"><div class="titlepage"><div><div><h3 class="title"><a id="using.exceptions.biblio"></a>Bibliography</h3></div></div></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.2"></a><p><span class="title"><em>
|
||||
</pre></div></div><div class="bibliography"><div class="titlepage"><div><div><h3 class="title"><a id="using.exceptions.biblio"></a>Bibliography</h3></div></div></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.2"></a><p><span class="title"><em>
|
||||
<a class="link" href="http://www.opengroup.org/austin/" target="_top">
|
||||
System Interface Definitions, Issue 7 (IEEE Std. 1003.1-2008)
|
||||
</a>
|
||||
@ -274,40 +329,44 @@ is called.
|
||||
. </span><span class="copyright">Copyright © 2008
|
||||
The Open Group/The Institute of Electrical and Electronics
|
||||
Engineers, Inc.
|
||||
. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.3"></a><p><span class="title"><em>
|
||||
. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.3"></a><p><span class="title"><em>
|
||||
<a class="link" href="https://www.boost.org/community/error_handling.html" target="_top">
|
||||
Error and Exception Handling
|
||||
</a>
|
||||
</em>. </span><span class="author"><span class="firstname">David</span> <span class="surname">Abrahams </span>. </span><span class="publisher"><span class="publishername">
|
||||
Boost
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.4"></a><p><span class="title"><em>
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.4"></a><p><span class="title"><em>
|
||||
<a class="link" href="https://www.boost.org/community/exception_safety.html" target="_top">
|
||||
Exception-Safety in Generic Components
|
||||
</a>
|
||||
</em>. </span><span class="author"><span class="firstname">David</span> <span class="surname">Abrahams</span>. </span><span class="publisher"><span class="publishername">
|
||||
Boost
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.5"></a><p><span class="title"><em>
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.5"></a><p><span class="title"><em>
|
||||
<a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1077.pdf" target="_top">
|
||||
Standard Library Exception Policy
|
||||
</a>
|
||||
</em>. </span><span class="author"><span class="firstname">Matt</span> <span class="surname">Austern</span>. </span><span class="publisher"><span class="publishername">
|
||||
WG21 N1077
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.6"></a><p><span class="title"><em>
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.6"></a><p><span class="title"><em>
|
||||
<a class="link" href="http://gcc.gnu.org/ml/gcc-patches/2001-03/msg00661.html" target="_top">
|
||||
ia64 c++ abi exception handling
|
||||
</a>
|
||||
</em>. </span><span class="author"><span class="firstname">Richard</span> <span class="surname">Henderson</span>. </span><span class="publisher"><span class="publishername">
|
||||
GNU
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.7"></a><p><span class="title"><em>
|
||||
. </span></span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.7"></a><p><span class="title"><em>
|
||||
<a class="link" href="https://www.stroustrup.com/3rd_safe.pdf" target="_top">
|
||||
Appendix E: Standard-Library Exception Safety
|
||||
</a>
|
||||
</em>. </span><span class="author"><span class="firstname">Bjarne</span> <span class="surname">Stroustrup</span>. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.8"></a><p><span class="citetitle"><em class="citetitle">
|
||||
</em>. </span><span class="author"><span class="firstname">Bjarne</span> <span class="surname">Stroustrup</span>. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.8"></a><p><span class="citetitle"><em class="citetitle">
|
||||
Exceptional C++
|
||||
</em>. </span><span class="pagenums">
|
||||
Exception-Safety Issues and Techniques
|
||||
. </span><span class="author"><span class="firstname">Herb</span> <span class="surname">Sutter</span>. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.9.9"></a><p><span class="title"><em>
|
||||
. </span><span class="author"><span class="firstname">Herb</span> <span class="surname">Sutter</span>. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.9"></a><p><span class="title"><em>
|
||||
<a class="link" href="http://gcc.gnu.org/PR25191" target="_top">
|
||||
GCC Bug 25191: exception_defines.h #defines try/catch
|
||||
</a>
|
||||
</em>. </span></p></div><div class="biblioentry"><a id="id-1.3.3.4.9.10.10"></a><p><span class="title"><em>
|
||||
<a class="link" href="https://www.gnu.org/software/libc/manual/html_node/Tunables.html" target="_top">
|
||||
Tunables, The GNU C Library
|
||||
</a>
|
||||
</em>. </span></p></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="using_concurrency.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="using.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="debug.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Concurrency </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Debugging Support</td></tr></table></div></body></html>
|
@ -366,6 +366,11 @@
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><code>--disable-libstdcxx-hosted</code></term>
|
||||
<listitem>
|
||||
<para>This is an alias for <code>--disable-hosted-libstdcxx</code>.</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><code>--disable-libstdcxx-verbose</code></term>
|
||||
<listitem>
|
||||
<para>
|
||||
@ -446,6 +451,24 @@
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><code>--enable-libstdcxx-static-eh-pool</code></term>
|
||||
<listitem>
|
||||
<para>Use a fixed-size static buffer for the emergency exception handling
|
||||
pool (see <xref linkend="intro.using.exception.alloc"/>). The default
|
||||
is to allocate the pool on program startup using <code>malloc</code>.
|
||||
With this option, a static buffer will be provided by libstdc++ instead.
|
||||
This does not change the library ABI.
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
<varlistentry><term><code>--with-libstdcxx-eh-pool-obj-count=NUM</code></term>
|
||||
<listitem>
|
||||
<para>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.
|
||||
</para>
|
||||
</listitem></varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
@ -1080,4 +1080,13 @@ and later.
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="api.rel_131"><info><title><constant>13</constant></title></info>
|
||||
|
||||
<para>
|
||||
Tunables <variable>glibcxx.eh_pool.obj_count</variable> and
|
||||
<variable>glibcxx.eh_pool.obj_size</variable> were added.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
@ -188,6 +188,87 @@ exception neutrality and exception safety.
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="intro.using.exception.alloc" xreflabel="Memory allocation for exceptions"><info><title>Memory allocation</title></info>
|
||||
|
||||
<para>
|
||||
When the program throws an exception the runtime will obtain storage for
|
||||
a <code>__cxa_exception</code> header and the thrown object itself.
|
||||
Libstdc++ will try to use <code>malloc</code> to obtain storage,
|
||||
but provides an emergency buffer to be used if malloc fails,
|
||||
as described by the <link xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xlink:href="https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#imp-emergency">Itanium
|
||||
exception handling ABI</link>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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 <code>std::bad_alloc</code>.
|
||||
The total size of the buffer is scaled appropriately for the target.
|
||||
Specifically it depends on <code>sizeof(void*)</code>, 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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
By default, libstdc++ will use <code>malloc</code> to allocate the buffer
|
||||
on program startup.
|
||||
<xref linkend="manual.intro.setup.configure"/> libstdc++ with the
|
||||
<code>--enable-libstdcxx-static-eh-pool</code> option will make it
|
||||
use a static buffer instead of using <code>malloc</code>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The buffer size is chosen automatically, but can be overridden
|
||||
by configuring with <code>--with-libstdcxx-eh-pool-obj-count=NUM</code>,
|
||||
where <code>NUM</code> is the number of simultaneous allocations that
|
||||
should be supported. The size of the pool will be sufficient for
|
||||
<code>NUM</code> exceptions of <code>6 * sizeof(void*)</code> bytes,
|
||||
plus another <code>NUM</code> exceptions captured in
|
||||
<classname>std::exception_ptr</classname> and rethrown using
|
||||
<code>std::rethrow_exception</code>. 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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
For a dynamic buffer, the default size can also be changed at runtime,
|
||||
per-process, via the <literal>GLIBCXX_TUNABLES</literal> environment
|
||||
variable.
|
||||
The <literal>GLIBCXX_TUNABLES</literal> environment variable should be
|
||||
a string of colon-separated <emphasis>name=value</emphasis> pairs. The
|
||||
following names will be recognized, with the specified semantics:
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><code>glibcxx.eh_pool.obj_count</code></term>
|
||||
<listitem>
|
||||
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
|
||||
<code>--with-libstdcxx-eh-pool-obj-count</code> option for
|
||||
<filename>configure</filename>.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><code>glibcxx.eh_pool.obj_size</code></term>
|
||||
<listitem>
|
||||
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
|
||||
<code>sizeof(void*)</code>. The default value is <literal>6</literal>
|
||||
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.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section xml:id="intro.using.exception.no" xreflabel="-fno-exceptions"><info><title>Doing without</title></info>
|
||||
|
||||
<para>
|
||||
@ -538,6 +619,15 @@ is called.
|
||||
</title>
|
||||
</biblioentry>
|
||||
|
||||
<biblioentry>
|
||||
<title>
|
||||
<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>
|
||||
</title>
|
||||
</biblioentry>
|
||||
|
||||
</bibliography>
|
||||
|
||||
</section>
|
||||
|
@ -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@
|
||||
|
@ -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 = \
|
||||
|
@ -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 = \
|
||||
|
@ -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 <bits/c++config.h>
|
||||
#include <cstdlib>
|
||||
#if _GLIBCXX_HOSTED
|
||||
#include <cstring>
|
||||
#endif
|
||||
#include <climits>
|
||||
#include <exception>
|
||||
#include <exception> // std::exception
|
||||
#include <new> // std::terminate
|
||||
#include <cstdlib> // std::malloc, std::free, std::strtoul
|
||||
#include <climits> // INT_MAX
|
||||
#include <bits/stl_function.h> // std::less
|
||||
#include "unwind-cxx.h"
|
||||
#include <ext/concurrence.h>
|
||||
#include <new>
|
||||
#if _GLIBCXX_HOSTED
|
||||
# include <string_view> // std::string_view
|
||||
# include <cstring> // std::strchr, std::memset
|
||||
# include <ext/concurrence.h> // __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<std::string_view, int> 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 <free_entry *> (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 <allocated_entry *>
|
||||
(reinterpret_cast <char *> (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 <char *> (ptr);
|
||||
return (p > arena
|
||||
&& p < arena + arena_size);
|
||||
std::less<const void*> 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);
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
@ -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@
|
||||
|
Loading…
Reference in New Issue
Block a user