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