#include <bits/c++config.h>
#include <exception>
#include <cstdlib>
#include "cxxabi.h"
#include "unwind-cxx.h"
#include "bits/gthr.h"
#if _GLIBCXX_HOSTED
using std::free;
using std::malloc;
#else
extern "C" void *malloc (std::size_t);
extern "C" void free(void *);
#endif
using namespace __cxxabiv1;
#if _GLIBCXX_HAVE_TLS
namespace
{
abi::__cxa_eh_globals*
get_global() throw()
{
static __thread abi::__cxa_eh_globals global;
return &global;
}
}
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() throw()
{ return get_global(); }
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() throw()
{ return get_global(); }
#else
#if ! defined(__APPLE__) || ! defined (__ppc__) || ! defined (PIC)
static __cxa_eh_globals eh_globals;
#if __GTHREADS
static void
eh_globals_dtor(void* ptr)
{
if (ptr)
{
__cxa_eh_globals* g = reinterpret_cast<__cxa_eh_globals*>(ptr);
__cxa_exception* exn = g->caughtExceptions;
__cxa_exception* next;
while (exn)
{
next = exn->nextException;
_Unwind_DeleteException(&exn->unwindHeader);
exn = next;
}
free(ptr);
}
}
struct __eh_globals_init
{
__gthread_key_t _M_key;
bool _M_init;
__eh_globals_init() : _M_init(false)
{
if (__gthread_active_p())
_M_init = __gthread_key_create(&_M_key, eh_globals_dtor) == 0;
}
~__eh_globals_init()
{
if (_M_init)
__gthread_key_delete(_M_key);
_M_init = false;
}
};
static __eh_globals_init init;
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() throw()
{
__cxa_eh_globals* g;
if (init._M_init)
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
else
g = &eh_globals;
return g;
}
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() throw()
{
__cxa_eh_globals* g;
if (init._M_init)
{
g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key));
if (!g)
{
void* v = malloc(sizeof(__cxa_eh_globals));
if (v == 0 || __gthread_setspecific(init._M_key, v) != 0)
std::terminate();
g = static_cast<__cxa_eh_globals*>(v);
g->caughtExceptions = 0;
g->uncaughtExceptions = 0;
}
}
else
g = &eh_globals;
return g;
}
#else
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals_fast() throw()
{ return &eh_globals; }
extern "C" __cxa_eh_globals*
__cxxabiv1::__cxa_get_globals() throw()
{ return &eh_globals; }
#endif
#else
extern "C" __cxa_eh_globals *
__cxxabiv1::__cxa_get_globals_fast () throw()
{
return (__cxa_eh_globals *) _keymgr_get_per_thread_data (KEYMGR_EH_GLOBALS_KEY);
}
extern "C" __cxa_eh_globals *
__cxxabiv1::__cxa_get_globals () throw()
{
__cxa_eh_globals *g;
g = (__cxa_eh_globals *) _keymgr_get_per_thread_data (KEYMGR_EH_GLOBALS_KEY);
if (! g)
{
if ((g = (__cxa_eh_globals *)
std::malloc (sizeof (__cxa_eh_globals))) == 0
|| KEYMGR_SET_PER_THREAD_DATA (KEYMGR_EH_GLOBALS_KEY, (void *) g) != 0)
std::terminate ();
g->caughtExceptions = 0;
g->uncaughtExceptions = 0;
}
return g;
}
#endif
#endif