]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/libsupc++/eh_alloc.cc
Update copyright years in libstdc++-v3/
[thirdparty/gcc.git] / libstdc++-v3 / libsupc++ / eh_alloc.cc
CommitLineData
52a11cbf 1// -*- C++ -*- Allocate exception objects.
aa118a03 2// Copyright (C) 2001-2014 Free Software Foundation, Inc.
52a11cbf 3//
cbecceb9 4// This file is part of GCC.
52a11cbf 5//
cbecceb9 6// GCC is free software; you can redistribute it and/or modify
52a11cbf 7// it under the terms of the GNU General Public License as published by
748086b7 8// the Free Software Foundation; either version 3, or (at your option)
52a11cbf
RH
9// any later version.
10//
cbecceb9 11// GCC is distributed in the hope that it will be useful,
52a11cbf
RH
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//
748086b7
JJ
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.
52a11cbf 19
748086b7
JJ
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/>.
52a11cbf
RH
24
25// This is derived from the C++ ABI for IA-64. Where we diverge
26// for cross-architecture compatibility are noted with "@@@".
27
b967bf25 28#include <bits/c++config.h>
52a11cbf 29#include <cstdlib>
4c24b21a 30#if _GLIBCXX_HOSTED
52a11cbf 31#include <cstring>
4c24b21a 32#endif
213c2316 33#include <climits>
93b85586 34#include <exception>
52a11cbf 35#include "unwind-cxx.h"
2e362c74 36#include <ext/concurrence.h>
52a11cbf 37
4c24b21a
MM
38#if _GLIBCXX_HOSTED
39using std::free;
40using std::malloc;
05a79eb6 41using std::memset;
4c24b21a 42#else
3cbc7af0
BK
43// In a freestanding environment, these functions may not be available
44// -- but for now, we assume that they are.
4c24b21a
MM
45extern "C" void *malloc (std::size_t);
46extern "C" void free(void *);
656032b8 47extern "C" void *memset (void *, int, std::size_t);
4c24b21a 48#endif
52a11cbf 49
4c24b21a 50using namespace __cxxabiv1;
52a11cbf
RH
51
52// ??? How to control these parameters.
53
54// Guess from the size of basic types how large a buffer is reasonable.
55// Note that the basic c++ exception header has 13 pointers and 2 ints,
56// so on a system with PSImode pointers we're talking about 56 bytes
57// just for overhead.
58
59#if INT_MAX == 32767
60# define EMERGENCY_OBJ_SIZE 128
61# define EMERGENCY_OBJ_COUNT 16
3cc6dd4d 62#elif !defined (_GLIBCXX_LLP64) && LONG_MAX == 2147483647
52a11cbf
RH
63# define EMERGENCY_OBJ_SIZE 512
64# define EMERGENCY_OBJ_COUNT 32
65#else
66# define EMERGENCY_OBJ_SIZE 1024
67# define EMERGENCY_OBJ_COUNT 64
68#endif
69
70#ifndef __GTHREADS
71# undef EMERGENCY_OBJ_COUNT
72# define EMERGENCY_OBJ_COUNT 4
73#endif
74
75#if INT_MAX == 32767 || EMERGENCY_OBJ_COUNT <= 32
76typedef unsigned int bitmask_type;
77#else
3cc6dd4d
KT
78#if defined (_GLIBCXX_LLP64)
79typedef unsigned long long bitmask_type;
80#else
52a11cbf
RH
81typedef unsigned long bitmask_type;
82#endif
3cc6dd4d 83#endif
52a11cbf
RH
84
85
86typedef char one_buffer[EMERGENCY_OBJ_SIZE] __attribute__((aligned));
87static one_buffer emergency_buffer[EMERGENCY_OBJ_COUNT];
88static bitmask_type emergency_used;
89
30a333ce
PC
90static __cxa_dependent_exception dependents_buffer[EMERGENCY_OBJ_COUNT];
91static bitmask_type dependents_used;
92
2e362c74 93namespace
52a11cbf 94{
2e362c74
BK
95 // A single mutex controlling emergency allocations.
96 __gnu_cxx::__mutex emergency_mutex;
52a11cbf 97}
52a11cbf
RH
98
99extern "C" void *
50da34bb 100__cxxabiv1::__cxa_allocate_exception(std::size_t thrown_size) _GLIBCXX_NOTHROW
52a11cbf
RH
101{
102 void *ret;
103
c4bca01b 104 thrown_size += sizeof (__cxa_refcounted_exception);
4c24b21a 105 ret = malloc (thrown_size);
52a11cbf
RH
106
107 if (! ret)
108 {
2e362c74 109 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
52a11cbf
RH
110
111 bitmask_type used = emergency_used;
112 unsigned int which = 0;
113
f847167e
NS
114 if (thrown_size > EMERGENCY_OBJ_SIZE)
115 goto failed;
52a11cbf
RH
116 while (used & 1)
117 {
118 used >>= 1;
119 if (++which >= EMERGENCY_OBJ_COUNT)
f847167e 120 goto failed;
52a11cbf
RH
121 }
122
123 emergency_used |= (bitmask_type)1 << which;
124 ret = &emergency_buffer[which][0];
125
f847167e 126 failed:;
2e362c74 127
f847167e
NS
128 if (!ret)
129 std::terminate ();
52a11cbf
RH
130 }
131
39609077
RH
132 // We have an uncaught exception as soon as we allocate memory. This
133 // yields uncaught_exception() true during the copy-constructor that
134 // initializes the exception object. See Issue 475.
135 __cxa_eh_globals *globals = __cxa_get_globals ();
136 globals->uncaughtExceptions += 1;
137
c4bca01b 138 memset (ret, 0, sizeof (__cxa_refcounted_exception));
52a11cbf 139
c4bca01b 140 return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
52a11cbf
RH
141}
142
143
144extern "C" void
50da34bb 145__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW
52a11cbf 146{
20fdc40c 147 char *base = (char *) emergency_buffer;
52a11cbf 148 char *ptr = (char *) vptr;
20fdc40c
BE
149 if (ptr >= base
150 && ptr < base + sizeof (emergency_buffer))
52a11cbf 151 {
2e362c74 152 const unsigned int which
20fdc40c 153 = (unsigned) (ptr - base) / EMERGENCY_OBJ_SIZE;
52a11cbf 154
2e362c74 155 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
52a11cbf 156 emergency_used &= ~((bitmask_type)1 << which);
52a11cbf
RH
157 }
158 else
c4bca01b 159 free (ptr - sizeof (__cxa_refcounted_exception));
52a11cbf 160}
30a333ce
PC
161
162
163extern "C" __cxa_dependent_exception*
50da34bb 164__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW
30a333ce
PC
165{
166 __cxa_dependent_exception *ret;
167
168 ret = static_cast<__cxa_dependent_exception*>
169 (malloc (sizeof (__cxa_dependent_exception)));
170
171 if (!ret)
172 {
173 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
174
175 bitmask_type used = dependents_used;
176 unsigned int which = 0;
177
178 while (used & 1)
179 {
180 used >>= 1;
181 if (++which >= EMERGENCY_OBJ_COUNT)
182 goto failed;
183 }
184
185 dependents_used |= (bitmask_type)1 << which;
186 ret = &dependents_buffer[which];
187
188 failed:;
189
190 if (!ret)
191 std::terminate ();
192 }
193
194 // We have an uncaught exception as soon as we allocate memory. This
195 // yields uncaught_exception() true during the copy-constructor that
196 // initializes the exception object. See Issue 475.
197 __cxa_eh_globals *globals = __cxa_get_globals ();
198 globals->uncaughtExceptions += 1;
199
200 memset (ret, 0, sizeof (__cxa_dependent_exception));
201
202 return ret;
203}
204
205
206extern "C" void
207__cxxabiv1::__cxa_free_dependent_exception
50da34bb 208 (__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW
30a333ce
PC
209{
210 char *base = (char *) dependents_buffer;
211 char *ptr = (char *) vptr;
212 if (ptr >= base
213 && ptr < base + sizeof (dependents_buffer))
214 {
215 const unsigned int which
216 = (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
217
218 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
219 dependents_used &= ~((bitmask_type)1 << which);
220 }
221 else
222 free (vptr);
223}