Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. // -*- C++ -*- Manage the thread-local exception globals.
  2. // Copyright (C) 2001-2013 Free Software Foundation, Inc.
  3. //
  4. // This file is part of GCC.
  5. //
  6. // GCC is free software; you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation; either version 3, or (at your option)
  9. // any later version.
  10. //
  11. // GCC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. // GNU General Public License for more details.
  15. //
  16. // Under Section 7 of GPL version 3, you are granted additional
  17. // permissions described in the GCC Runtime Library Exception, version
  18. // 3.1, as published by the Free Software Foundation.
  19.  
  20. // You should have received a copy of the GNU General Public License and
  21. // a copy of the GCC Runtime Library Exception along with this program;
  22. // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
  23. // <http://www.gnu.org/licenses/>.
  24.  
  25. #include <bits/c++config.h>
  26. #include <exception>
  27. #include <cstdlib>
  28. #include "cxxabi.h"
  29. #include "unwind-cxx.h"
  30. #include "bits/gthr.h"
  31.  
  32. #if _GLIBCXX_HOSTED
  33. using std::free;
  34. using std::malloc;
  35. #else
  36. // In a freestanding environment, these functions may not be
  37. // available -- but for now, we assume that they are.
  38. extern "C" void *malloc (std::size_t);
  39. extern "C" void free(void *);
  40. #endif
  41.  
  42. using namespace __cxxabiv1;
  43.  
  44. #if _GLIBCXX_HAVE_TLS
  45.  
  46. namespace
  47. {
  48.   abi::__cxa_eh_globals*
  49.   get_global() _GLIBCXX_NOTHROW
  50.   {
  51.     static __thread abi::__cxa_eh_globals global;
  52.     return &global;
  53.   }
  54. } // anonymous namespace
  55.  
  56. extern "C" __cxa_eh_globals*
  57. __cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
  58. { return get_global(); }
  59.  
  60. extern "C" __cxa_eh_globals*
  61. __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
  62. { return get_global(); }
  63.  
  64.  
  65. #else
  66.  
  67. // Single-threaded fallback buffer.
  68. static __cxa_eh_globals eh_globals;
  69.  
  70. #if __GTHREADS
  71.  
  72. static void
  73. eh_globals_dtor(void* ptr)
  74. {
  75.   if (ptr)
  76.     {
  77.       __cxa_eh_globals* g = reinterpret_cast<__cxa_eh_globals*>(ptr);
  78.       __cxa_exception* exn = g->caughtExceptions;
  79.       __cxa_exception* next;
  80.       while (exn)
  81.         {
  82.           next = exn->nextException;
  83.           _Unwind_DeleteException(&exn->unwindHeader);
  84.           exn = next;
  85.         }
  86.       free(ptr);
  87.     }
  88. }
  89.  
  90. struct __eh_globals_init
  91. {
  92.   __gthread_key_t       _M_key;
  93.   bool                  _M_init;
  94.  
  95.   __eh_globals_init() : _M_init(false)
  96.   {
  97.     if (__gthread_active_p())
  98.       _M_init = __gthread_key_create(&_M_key, eh_globals_dtor) == 0;
  99.   }
  100.  
  101.   ~__eh_globals_init()
  102.   {
  103.     if (_M_init)
  104.       __gthread_key_delete(_M_key);
  105.     _M_init = false;
  106.   }
  107. };
  108.  
  109. static __eh_globals_init init;
  110.  
  111. extern "C" __cxa_eh_globals*
  112. __cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
  113. {
  114.   __cxa_eh_globals* g;
  115.   if (init._M_init)
  116.     g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
  117.   else
  118.     g = &eh_globals;
  119.   return g;
  120. }
  121.  
  122. extern "C" __cxa_eh_globals*
  123. __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
  124. {
  125.   __cxa_eh_globals* g;
  126.   if (init._M_init)
  127.     {
  128.       g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
  129.       if (!g)
  130.         {
  131.           void* v = malloc(sizeof(__cxa_eh_globals));
  132.           if (v == 0 || __gthread_setspecific(init._M_key, v) != 0)
  133.             std::terminate();
  134.           g = static_cast<__cxa_eh_globals*>(v);
  135.           g->caughtExceptions = 0;
  136.           g->uncaughtExceptions = 0;
  137. #ifdef __ARM_EABI_UNWINDER__
  138.           g->propagatingExceptions = 0;
  139. #endif
  140.         }
  141.     }
  142.   else
  143.     g = &eh_globals;
  144.   return g;
  145. }
  146.  
  147. #else
  148.  
  149. extern "C" __cxa_eh_globals*
  150. __cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW
  151. { return &eh_globals; }
  152.  
  153. extern "C" __cxa_eh_globals*
  154. __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW
  155. { return &eh_globals; }
  156.  
  157. #endif
  158.  
  159. #endif
  160.