Subversion Repositories Kolibri OS

Rev

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

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