Message ID | 20161213135000.GP6326@redhat.com |
---|---|
State | New |
Headers | show |
On Tue, Dec 13, 2016 at 2:50 PM, Jonathan Wakely <jwakely@redhat.com> wrote: > This patch allows the size of the emergency buffer for exception > handling to be controlled by a build-time macro (to avoid dynamic > allocation) or by a run-time environment variable (to allocate a > larger or smaller buffer). > > This will have to wait for the next stage 1 now, as it's too late for > GCC 7, but this shows what I'm thinking about and so might avoid > anybody else reinventing the wheel. > > The patch doesn't include documentation updates for the manual, which > would be needed to explain the use of the macro and the env var. We > could also add a --with-libstdcxx-static-eh-pool=N configure flag to > make it easier to set the macro. Looks reasonable. But I wonder whether we'd want the default arena size to be configurable as well, thus split static-eh-pool=N into default-eh-pool-size=N and -static-eh-pool (without =N). Also maybe N should be the number of exception objects rather than bytes? Otherwise a target independent N is hard to specify for say, a distribution that wants either a different default or a static buffer. Richard. >
On 13 December 2016 at 16:42, Richard Biener <richard.guenther@gmail.com> wrote: > Also maybe N should be the number of exception objects rather > than bytes? Otherwise a target independent N is hard to specify > for say, a distribution that wants either a different default or a > static buffer. But how to specify the number of exception objects that may have different sizes?
On Tue, Dec 13, 2016 at 3:45 PM, Ville Voutilainen <ville.voutilainen@gmail.com> wrote: > On 13 December 2016 at 16:42, Richard Biener <richard.guenther@gmail.com> wrote: >> Also maybe N should be the number of exception objects rather >> than bytes? Otherwise a target independent N is hard to specify >> for say, a distribution that wants either a different default or a >> static buffer. > > > But how to specify the number of exception objects that may have > different sizes? We have EMERGENCY_OBJ_SIZE for this (yeah, some guesstimate) which can be easily target configured in libstdc++ itself. We possibly should split it into a sizeof () of the exception header plus some payload guesstimate. Richard.
On 13 December 2016 at 16:52, Richard Biener <richard.guenther@gmail.com> wrote: > On Tue, Dec 13, 2016 at 3:45 PM, Ville Voutilainen > <ville.voutilainen@gmail.com> wrote: >> On 13 December 2016 at 16:42, Richard Biener <richard.guenther@gmail.com> wrote: >>> Also maybe N should be the number of exception objects rather >>> than bytes? Otherwise a target independent N is hard to specify >>> for say, a distribution that wants either a different default or a >>> static buffer. >> >> >> But how to specify the number of exception objects that may have >> different sizes? > > We have EMERGENCY_OBJ_SIZE for this (yeah, some guesstimate) > which can be easily target configured in libstdc++ itself. We possibly > should split it into a sizeof () of the exception header plus some > payload guesstimate. Ah, yes, that's what the patch does with the default-size when there is nothing in the environment to customize the value. Makes sense. I don't know whether a separate byte-wise count would be useful, I must admit I have no field experience with such tunings.
commit 4e021613dcda14dfec5c88286f8faf3001afcd17 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Dec 13 13:23:48 2016 +0000 Allow pool size to be set by macro or env var diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 7d0fafa..be4679e 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -257,6 +257,7 @@ if $GLIBCXX_IS_NATIVE; then AC_CHECK_FUNCS(__cxa_thread_atexit_impl) AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc) + AC_CHECK_FUNCS(secure_getenv) # For iconv support. AM_ICONV diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4 index 8cc788c..c01213a 100644 --- a/libstdc++-v3/crossconfig.m4 +++ b/libstdc++-v3/crossconfig.m4 @@ -184,6 +184,7 @@ case "${host}" in GCC_CHECK_TLS AC_CHECK_FUNCS(__cxa_thread_atexit_impl) AC_CHECK_FUNCS(aligned_alloc posix_memalign memalign _aligned_malloc) + AC_CHECK_FUNCS(secure_getenv) AM_ICONV ;; *-mingw32*) diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc index d362e40..571fe6b 100644 --- a/libstdc++-v3/libsupc++/eh_alloc.cc +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -29,6 +29,7 @@ #include <cstdlib> #if _GLIBCXX_HOSTED #include <cstring> +#include <cerrno> #endif #include <climits> #include <exception> @@ -36,6 +37,14 @@ #include <ext/concurrence.h> #include <new> +#ifdef STATIC_EH_ALLOC_POOL_BYTES +char* alloc_pool_arena(std::size_t& size) +{ + size = STATIC_EH_ALLOC_POOL_BYTES; + static alignas(void*) char arena[STATIC_EH_ALLOC_POOL_BYTES]; + return arena; +} +#else #if _GLIBCXX_HOSTED using std::free; using std::malloc; @@ -50,8 +59,6 @@ extern "C" void *memset (void *, int, std::size_t); using namespace __cxxabiv1; -// ??? How to control these parameters. - // 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 @@ -73,6 +80,32 @@ using namespace __cxxabiv1; # define EMERGENCY_OBJ_COUNT 4 #endif +char *alloc_pool_arena(std::size_t& size) +{ + size = 0; +#if _GLIBCXX_HOSTED + const char *name = "GLIBCXX_EH_ARENA_SIZE"; + char *env = nullptr; +# ifdef _GLIBCXX_HAVE_SECURE_GETENV + env = ::secure_getenv (name); +# else + env = std::getenv (name); +# endif + if (env) + { + char *end; + size = strtoul(env, &end, 0); + if (*end || (size == ULONG_MAX && errno == ERANGE)) + size = 0; + } +#endif // _GLIBCXX_HOSTED + if (size == 0) + size = (EMERGENCY_OBJ_SIZE * EMERGENCY_OBJ_COUNT + + EMERGENCY_OBJ_COUNT * sizeof (__cxa_dependent_exception)); + return (char *)malloc (size); +} +#endif // STATIC_EH_ALLOC_POOL_BYTES + namespace __gnu_cxx { void __freeres(); @@ -107,7 +140,7 @@ namespace // The free-list free_entry *first_free_entry; // The arena itself - we need to keep track of these only - // to implement in_pool. + // to implement in_pool and __freeres. char *arena; std::size_t arena_size; @@ -116,11 +149,8 @@ namespace pool::pool() { - // 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)); - arena = (char *)malloc (arena_size); + // Allocate the arena. + arena = alloc_pool_arena (arena_size); if (!arena) { // If the allocation failed go without an emergency pool. @@ -255,11 +285,13 @@ namespace __gnu_cxx void __freeres() { +#ifndef STATIC_EH_ALLOC_POOL_BYTES if (emergency_pool.arena) { ::free(emergency_pool.arena); emergency_pool.arena = 0; } +#endif } }