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