111
|
1 // -*- C++ -*- Manage the thread-local exception globals.
|
145
|
2 // Copyright (C) 2001-2020 Free Software Foundation, Inc.
|
111
|
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
|