]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/libsupc++/eh_alloc.cc
re PR libstdc++/64680 (basic_regex::operator= does not reset flags)
[thirdparty/gcc.git] / libstdc++-v3 / libsupc++ / eh_alloc.cc
CommitLineData
52a11cbf 1// -*- C++ -*- Allocate exception objects.
5624e564 2// Copyright (C) 2001-2015 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
c4bca01b 132 memset (ret, 0, sizeof (__cxa_refcounted_exception));
52a11cbf 133
c4bca01b 134 return (void *)((char *)ret + sizeof (__cxa_refcounted_exception));
52a11cbf
RH
135}
136
137
138extern "C" void
50da34bb 139__cxxabiv1::__cxa_free_exception(void *vptr) _GLIBCXX_NOTHROW
52a11cbf 140{
20fdc40c 141 char *base = (char *) emergency_buffer;
52a11cbf 142 char *ptr = (char *) vptr;
20fdc40c
BE
143 if (ptr >= base
144 && ptr < base + sizeof (emergency_buffer))
52a11cbf 145 {
2e362c74 146 const unsigned int which
20fdc40c 147 = (unsigned) (ptr - base) / EMERGENCY_OBJ_SIZE;
52a11cbf 148
2e362c74 149 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
52a11cbf 150 emergency_used &= ~((bitmask_type)1 << which);
52a11cbf
RH
151 }
152 else
c4bca01b 153 free (ptr - sizeof (__cxa_refcounted_exception));
52a11cbf 154}
30a333ce
PC
155
156
157extern "C" __cxa_dependent_exception*
50da34bb 158__cxxabiv1::__cxa_allocate_dependent_exception() _GLIBCXX_NOTHROW
30a333ce
PC
159{
160 __cxa_dependent_exception *ret;
161
162 ret = static_cast<__cxa_dependent_exception*>
163 (malloc (sizeof (__cxa_dependent_exception)));
164
165 if (!ret)
166 {
167 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
168
169 bitmask_type used = dependents_used;
170 unsigned int which = 0;
171
172 while (used & 1)
173 {
174 used >>= 1;
175 if (++which >= EMERGENCY_OBJ_COUNT)
176 goto failed;
177 }
178
179 dependents_used |= (bitmask_type)1 << which;
180 ret = &dependents_buffer[which];
181
182 failed:;
183
184 if (!ret)
185 std::terminate ();
186 }
187
30a333ce
PC
188 memset (ret, 0, sizeof (__cxa_dependent_exception));
189
190 return ret;
191}
192
193
194extern "C" void
195__cxxabiv1::__cxa_free_dependent_exception
50da34bb 196 (__cxa_dependent_exception *vptr) _GLIBCXX_NOTHROW
30a333ce
PC
197{
198 char *base = (char *) dependents_buffer;
199 char *ptr = (char *) vptr;
200 if (ptr >= base
201 && ptr < base + sizeof (dependents_buffer))
202 {
203 const unsigned int which
204 = (unsigned) (ptr - base) / sizeof (__cxa_dependent_exception);
205
206 __gnu_cxx::__scoped_lock sentry(emergency_mutex);
207 dependents_used &= ~((bitmask_type)1 << which);
208 }
209 else
210 free (vptr);
211}