This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Allow emergency EH pool size to be controlled (for stage 1)


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.


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
   }
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]